Reworked resizing a course to shift collisions down a layer instead of blocking

This commit is contained in:
PMKuipers 2024-01-26 23:43:02 +01:00
parent d9bcb71a46
commit 546bff0659
3 changed files with 112 additions and 46 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -2186,44 +2186,7 @@ export default {
}, },
maxSpan(){ maxSpan(){
// Determine the maximum span for components in this slot // Determine the maximum span for components in this slot
// Used for setting the max in the timing adjustment screen(s) return this.page.periods - this.slotindex + 1;
// And for checking the filter types
// Assume this slot is first one available
let freeIndex = this.slotindex;
// Determine last free slot following this one in the layer
for(let i = this.slotindex + 1; i <= this.page.periods; i++){
if(this.line.slots && this.line.slots[i] && this.line.slots[i].courses){
const clist = this.line.slots[i].courses;
const flist = this.line.slots[i-1].filters; // next filter is in the same slot
let busy = false;
for(const ix in clist) {
if( clist[ix].layer == this.layer) {
busy = true; // slot is busy in this layer.
break;
}
}
for(const ix in flist) {
if( flist[ix].layer == this.layer) {
busy = true; // slot is busy in this layer.
break;
}
}
if(! busy) {
// slot is free in this layer
freeIndex = i;
} else {
break; // stop checking next slots
}
} else {
break; // stop processing
}
}
// calculate span from that
return freeIndex - this.slotindex + 1;
}, },
makeType(item){ makeType(item){
return { return {
@ -2303,6 +2266,7 @@ export default {
ref="timingChecker" ref="timingChecker"
:maxspan="maxSpan()" :maxspan="maxSpan()"
:page="page" :page="page"
:line="line"
:period="period" :period="period"
v-model="value[itemidx]" v-model="value[itemidx]"
></t-item-timing-checker> ></t-item-timing-checker>
@ -2317,7 +2281,10 @@ export default {
type: Object, // t-item model type: Object, // t-item model
}, },
page: { page: {
type: Object, // Studyplan data type: Object, // Studyplanpage
},
line: {
type: Object, // Studyline
}, },
period: { period: {
type: Object, // Studyplan data type: Object, // Studyplan data
@ -2348,7 +2315,7 @@ export default {
return false; return false;
} }
} else { } else {
debug.warn("Timing thing not proper configured",self.value,self.period,self.maxspan); debug.warn("Timing thing not properly configured",self.value,self.period,self.maxspan);
return false; return false;
} }
}, },
@ -2366,8 +2333,7 @@ export default {
}; };
}, },
methods: { methods: {
validate_course_period() {
validate_course_period(force) {
const self = this; const self = this;
debug.info("Validating course and period"); debug.info("Validating course and period");
@ -2394,6 +2360,9 @@ export default {
debug.info("Course timing matches period",self.datechanger); debug.info("Course timing matches period",self.datechanger);
} }
}, },
has_filter() {
const slots = this.page.slots;
},
change_course_period() { change_course_period() {
const self=this; const self=this;
// Save the state // Save the state
@ -2413,8 +2382,99 @@ export default {
self.$emit("input",self.value); self.$emit("input",self.value);
}); });
}, },
checkFilterSlotBusy(slotindex) {
debug.info("checking filter",this.line.slots, slotindex,this.value.layer);
if (this.line.slots[slotindex]) {
const list = this.line.slots[slotindex].filters;
for(const ix in list) {
if( list[ix].layer == this.value.layer) {
debug.info("Busy:",list[ix]);
return list[ix];
}
}
}
return null;
},
nextFreeFilterLayer(slotindex) {
const layer = this.value.layer;
const list = this.line.slots[slotindex].filters;
const usedLayers = [];
for(const ix in list) {
usedLayers.push(list[ix].layer);
}
let nextlyr = layer+1;
while (usedLayers.includes(nextlyr)) {
nextlyr++;
}
return nextlyr;
},
checkCourseSlotBusy(slotindex) {
debug.info("checking ",this.line.slots, slotindex,this.value.layer);
if (this.line.slots[slotindex]) {
const list = this.line.slots[slotindex].courses;
for(const ix in list) {
if( list[ix].layer == this.value.layer) {
debug.info("Busy:",list[ix]);
return list[ix];
}
}
}
return null;
},
nextFreeCourseLayer(slotindex) {
const layer = this.value.layer;
const list = this.line.slots[slotindex].courses;
const usedLayers = [];
for(const ix in list) {
usedLayers.push(list[ix].layer);
}
let nextlyr = layer+1;
while (usedLayers.includes(nextlyr)) {
nextlyr++;
}
return nextlyr;
},
shift_collisions(span) {
// Check all periods for collision
const shiftfilters = [];
const shiftcourses = [];
const items = [];
for(let i = this.value.slot; i < this.value.slot + span; i++) {
const busyFilter = this.checkFilterSlotBusy(i);
if (busyFilter) {
const nextlyr = this.nextFreeFilterLayer(i);
items.push({
id: busyFilter.id,
layer: nextlyr,
line_id: this.line.id,
slot: busyFilter.slot,
});
busyFilter.layer = nextlyr;
}
const busyCourse = this.checkCourseSlotBusy(i);
if (busyCourse && busyCourse.id != this.value.id) {
const nextlyr = this.nextFreeCourseLayer(i);
items.push({
id: busyCourse.id,
layer: nextlyr,
line_id: this.line.id,
slot: busyCourse.slot,
});
busyCourse.layer = nextlyr;
}
}
if (items.length > 0){
call([{
methodname: 'local_treestudyplan_reorder_studyitems',
args: { items: items }
}])[0].catch(notification.exception).done((response) => {
});
}
},
change_span(span) { change_span(span) {
const self=this; const self=this;
this.shift_collisions(span);
return call([{ return call([{
methodname: 'local_treestudyplan_set_studyitem_span', methodname: 'local_treestudyplan_set_studyitem_span',
args: { id: self.value.id, args: { id: self.value.id,
@ -2463,13 +2523,13 @@ export default {
</span> </span>
<span class="ml-1" v-b-tooltip.hover.bottomleft :title="text.periodspan_desc" <span class="ml-1" v-b-tooltip.hover.bottomleft :title="text.periodspan_desc"
>{{ text.periodspan >{{ text.periodspan
}}&nbsp;<b-form-select }}&nbsp;<b-form-select v-if="maxspan > 1"
class="" class=""
size="sm" @change="change_span" v-model="value.span"> size="sm" @change="change_span" v-model="value.span">
<b-form-select-option v-for="(n,i) in maxspan" :value='n' :key='i' <b-form-select-option v-for="(n,i) in maxspan" :value='n' :key='i'
>{{ n }}</b-form-select-option> >{{ n }}</b-form-select-option>
</b-form-select </b-form-select
>&nbsp;{{ ><span v-else>{{value.span}}</span>&nbsp;{{
(value.span == 1)?text.period.toLowerCase():text.periods.toLowerCase() (value.span == 1)?text.period.toLowerCase():text.periods.toLowerCase()
}}<i }}<i
class="fa fa-question-circle text-black-50" class="fa fa-question-circle text-black-50"
@ -2895,6 +2955,7 @@ export default {
@deleterq="deleteItem" @deleterq="deleteItem"
v-model="value" v-model="value"
:plan='plan' :plan='plan'
:line='line'
:page='page' :page='page'
:period='period' :period='period'
:maxspan='maxspan' :maxspan='maxspan'
@ -3033,6 +3094,10 @@ export default {
type: Object, type: Object,
default(){ return null;}, default(){ return null;},
}, },
line:{
type: Object,
default(){ return null;},
},
page: { page: {
type: Object, // PAge data type: Object, // PAge data
default() { return null;} default() { return null;}
@ -3199,6 +3264,7 @@ export default {
class="mt-1" class="mt-1"
:maxspan="maxspan" :maxspan="maxspan"
:page="page" :page="page"
:line="line"
:period="period" :period="period"
v-model="value" v-model="value"
></t-item-timing-checker> ></t-item-timing-checker>