Commit 30df6a30 authored by Jérome Perrin's avatar Jérome Perrin

Add a new GUI for Capacity Project

parent 9a18397c
......@@ -69,6 +69,8 @@
<div class="twelve columns">
<div id="wip_part_spreadsheet" style="display: none; overflow: scroll;"></div>
<div id="shift_spreadsheet" style="display: none; overflow: scroll"></div>
<div id="capacity_by_project_spreadsheet" style="display: none; overflow: scroll"></div>
<div id="capacity_by_station_spreadsheet" style="display: none; overflow: scroll"></div>
</div>
<div class="twelve columns">
......
......@@ -70,6 +70,8 @@
$('#shift_spreadsheet').hide();
$("#wip_part_spreadsheet").hide();
$('#capacity_by_project_spreadsheet').hide();
$('#capacity_by_station_spreadsheet').hide();
if (configuration['Dream-Configuration'].gui.wip_part_spreadsheet){
$("#wip_part_spreadsheet").show();
......@@ -77,6 +79,12 @@
if (configuration['Dream-Configuration'].gui.shift_spreadsheet){
$("#shift_spreadsheet").show();
}
if (configuration['Dream-Configuration'].gui.capacity_by_project_spreadsheet){
$("#capacity_by_project_spreadsheet").show();
}
if (configuration['Dream-Configuration'].gui.capacity_by_station_spreadsheet){
$("#capacity_by_station_spreadsheet").show();
}
try {
// spreadsheets
......@@ -90,6 +98,16 @@
var spreadsheet = $('#wip_part_spreadsheet');
spreadsheet.handsontable('populateFromArray', 0, 0, wip_part_spreadsheet_data);
}
var capacity_by_project_spreadsheet_data = data.capacity_by_project_spreadsheet;
if (capacity_by_project_spreadsheet_data !== undefined) {
var spreadsheet = $('#capacity_by_project_spreadsheet');
spreadsheet.handsontable('populateFromArray', 0, 0, capacity_by_project_spreadsheet_data);
}
var capacity_by_station_spreadsheet_data = data.capacity_by_station_spreadsheet;
if (capacity_by_station_spreadsheet_data !== undefined) {
var spreadsheet = $('#capacity_by_station_spreadsheet');
spreadsheet.handsontable('populateFromArray', 0, 0, capacity_by_station_spreadsheet_data);
}
var preference = data.preference !== undefined ?
data.preference : {};
......@@ -274,6 +292,8 @@
});
$("#job_schedule_spreadsheet").hide();
$("#shift_spreadsheet").hide();
$("#capacity_by_project_spreadsheet").hide();
$("#capacity_by_station_spreadsheet").hide();
}
});
});
......
......@@ -164,6 +164,52 @@
}
});
var capacity_by_project_spreadsheet = $('#capacity_by_project_spreadsheet');
var data = [
[
"Project Name",
"Sequence",
"Capacity Requirements"
]
];
capacity_by_project_spreadsheet.handsontable({
data: data,
minSpareRows: 1,
stretchH: 'all',
width: function () {
return $(window).width() -
capacity_by_project_spreadsheet.offset().left +
$(window).scrollLeft();
},
afterChange: function () {
priv.onDataChange();
}
});
var capacity_by_station_spreadsheet = $('#capacity_by_station_spreadsheet');
var data = [
[
"Machine",
"Day 0",
"Day 1",
"Day 2",
"Day 3",
]
];
capacity_by_station_spreadsheet.handsontable({
data: data,
minSpareRows: 1,
stretchH: 'all',
width: function () {
return $(window).width() -
capacity_by_station_spreadsheet.offset().left +
$(window).scrollLeft();
},
afterChange: function () {
priv.onDataChange();
}
});
};
priv.updateElementCoordinate = function (node_id, coordinate) {
......@@ -337,6 +383,14 @@
if (shift_spreadsheet.length > 0) {
data['shift_spreadsheet'] = shift_spreadsheet.handsontable('getData');
}
var capacity_by_project_spreadsheet = $('#capacity_by_project_spreadsheet');
if (capacity_by_project_spreadsheet.length > 0) {
data['capacity_by_project_spreadsheet'] = capacity_by_project_spreadsheet.handsontable('getData');
}
var capacity_by_station_spreadsheet = $('#capacity_by_station_spreadsheet');
if (capacity_by_station_spreadsheet.length > 0) {
data['capacity_by_station_spreadsheet'] = capacity_by_station_spreadsheet.handsontable('getData');
}
return data;
};
......
from copy import copy
import json
import time
import random
import operator
from datetime import datetime
from dream.simulation.GUI.Default import Simulation as DefaultSimulation
from dream.simulation.GUI.Default import schema
class Simulation(DefaultSimulation):
def getConfigurationDict(self):
conf = DefaultSimulation.getConfigurationDict(self)
conf["Dream-MachineJobShop"] = {
"property_list": [
schema["operationType"] # XXX always manual
],
"_class": 'Dream.MachineJobShop',
"name": 'Machine', # XXX or simply processing step ?
"short_id": "M",
}
conf["Dream-QueueJobShop"] = {
"property_list": [
schema["capacity"],
schema["schedulingRule"]
],
"_class": 'Dream.QueueJobShop',
"name": 'Queue',
"short_id": "Q",
}
conf["Dream-ExitJobShop"] = {
"_class": 'Dream.ExitJobShop',
"name": 'Exit',
"short_id": "E",
}
conf["Dream-Configuration"]["gui"]["wip_part_spreadsheet"] = 1
conf["Dream-Configuration"]["gui"]["job_schedule_spreadsheet"] = 1
conf["Dream-Configuration"]["gui"]["job_gantt"] = 1
conf["Dream-Configuration"]["gui"]["queue_stat"] = 1
conf["Dream-Configuration"]["gui"]["debug_json"] = 1
# remove tools that does not make sense here
conf.pop('Dream-Machine')
conf.pop('Dream-Queue')
conf.pop('Dream-Exit')
conf.pop('Dream-Repairman')
conf.pop('Dream-Source')
conf.pop('Dream-EventGenerator')
return conf
def getRouteList(self, sequence_list, processing_time_list, prerequisite_list):
# use to record which predecessor has been already done, used to avoid doing
# two times Decomposition
predecessor_set = set()
route_list = []
for j, sequence_step in enumerate(sequence_list):
route = {"stationIdsList": sequence_step.split("-"),
"processingTime": {"distributionType": "Fixed",
"mean": float(processing_time_list[j])},
"setupTime": {"distributionType": "Fixed",
"mean": .5}, # XXX hardcoded value
}
if prerequisite_list:
route["prerequisites"] = prerequisite_list
route_list.append(route)
return route_list
def getListFromString(self, my_string):
my_list = []
if not my_string in (None, ''):
my_list = my_string.split('-')
return my_list
def _preprocess(self, in_data):
""" Set the WIP in queue from spreadsheet data.
"""
data = copy(DefaultSimulation._preprocess(self, in_data))
self.data = data
now = datetime.now()
if data['general']['currentDate']:
now = datetime.strptime(data['general']['currentDate'], '%Y/%m/%d')
if 'wip_part_spreadsheet' in data:
wip_list = []
i = 0
wip_part_spreadsheet_length = len(data['wip_part_spreadsheet'])
while i < wip_part_spreadsheet_length:
value_list = data['wip_part_spreadsheet'][i]
if value_list[0] == 'Order ID' or not value_list[4]:
i += 1
continue
order_dict = {}
wip_list.append(order_dict)
order_id, due_date, priority, project_manager, part, part_type,\
sequence_list, processing_time_list, prerequisite_string = value_list
due_date = (datetime.strptime(due_date, '%Y/%m/%d') - now).days * 24
prerequisite_list = self.getListFromString(prerequisite_string)
sequence_list = sequence_list.split('-')
processing_time_list = processing_time_list.split('-')
order_dict["_class"] = "Dream.Order"
order_dict["id"] = "%i" % i # XXX hack, we use it in UI to retrieve spreadsheet line
order_dict["manager"] = project_manager
order_dict["name"] = order_id
order_dict["dueDate"] = due_date
# XXX make it dynamic by writing a function that will reuse the
# code available a bit after
order_dict["route"] = self.getRouteList(sequence_list, processing_time_list,
prerequisite_list)
i += 1
component_list = []
if i < wip_part_spreadsheet_length:
while data['wip_part_spreadsheet'][i][0] in (None, ''):
value_list = data['wip_part_spreadsheet'][i]
if value_list[4] in (None, ''):
break
order_id, due_date, priority, project_manager, part, part_type,\
sequence_list, processing_time_list, prerequisite_string = value_list
sequence_list = sequence_list.split('-')
prerequisite_list = self.getListFromString(prerequisite_string)
processing_time_list = processing_time_list.split('-')
component_dict = {}
component_dict["_class"] = "Dream.OrderComponent"
if part_type == "Mould":
component_dict["_class"] = "Dream.Mould"
component_dict["componentType"] = part_type
component_dict["id"] = "%i" % i # XXX hack, we use it in UI to retrieve spreadsheet line
component_dict["name"] = part
component_list.append(component_dict)
route_list = self.getRouteList(sequence_list, processing_time_list,
prerequisite_list)
if part_type == "Mould":
route_list = route_list[1:]
component_dict["route"] = route_list
i+=1
order_dict["componentsList"] = component_list
data["nodes"]["QStart"]["wip"] = wip_list # XXX
del(data['wip_part_spreadsheet'])
return data
from copy import copy
import json
import time
import random
import operator
from datetime import datetime
from dream.simulation.GUI.Default import Simulation as DefaultSimulation
from dream.simulation.GUI.Default import schema
class Simulation(DefaultSimulation):
def getConfigurationDict(self):
conf = DefaultSimulation.getConfigurationDict(self)
conf["Dream-AbstractCapacityStation"] = {
"property_list": [
],
"_class": 'Dream.AbstractCapacityStation',
"name": 'Station',
"short_id": "CS",
}
conf["Dream-Configuration"]["gui"]["capacity_by_project_spreadsheet"] = 1
conf["Dream-Configuration"]["gui"]["capacity_by_station_spreadsheet"] = 1
conf["Dream-Configuration"]["gui"]["job_schedule_spreadsheet"] = 1
conf["Dream-Configuration"]["gui"]["job_gantt"] = 0 # XXX does not work
conf["Dream-Configuration"]["gui"]["queue_stat"] = 1
conf["Dream-Configuration"]["gui"]["debug_json"] = 1
# remove tools that does not make sense here
conf.pop('Dream-Machine')
conf.pop('Dream-Queue')
conf.pop('Dream-Exit')
conf.pop('Dream-Repairman')
conf.pop('Dream-Source')
conf.pop('Dream-EventGenerator')
return conf
def _preprocess(self, in_data):
data = copy(DefaultSimulation._preprocess(self, in_data))
new_data = copy(data)
# remove not needed spreadsheet not to polute json
new_data.pop('shift_spreadsheet', None)
new_data.pop('wip_part_spreadsheet', None)
# read the spreadsheets
# a mapping station id -> list of interval capacity
available_capacity_by_station = dict()
for line in data.pop('capacity_by_station_spreadsheet')[1:]:
available_capacity_by_station[line[0]] = [float(x) for x in line[1:] if x]
# a mapping project id -> mapping station_id -> required capacity
required_capacity_by_project = dict()
for project_id, station_sequence, requirement_sequence \
in data['capacity_by_project_spreadsheet'][1:]:
if project_id:
required_capacity_by_project[project_id] = {}
for idx, capacity_station in enumerate(station_sequence.split('-')):
capacity_station = '%s_Station' % capacity_station.strip()
required_capacity_by_project[project_id][capacity_station] = \
float(requirement_sequence.split('-')[idx])
# implicitly add a Queue for wip
assert 'Qstart' not in new_data['nodes'], "reserved ID used"
wip = []
for project, capacityRequirementDict in \
required_capacity_by_project.items():
wip.append(
dict(_class='Dream.CapacityProject',
id=project,
name=project,
capacityRequirementDict=capacityRequirementDict))
new_data['nodes']['QStart'] = dict(
_class='Dream.Queue',
id='QStart',
name='Start Queue',
capacity=-1,
wip=wip)
# implicitly add a capacity station controller
assert 'CSC' not in new_data['nodes'], "reserved ID used"
new_data['nodes']['CSC'] = dict(
_class='Dream.CapacityStationController',
name='CSC',
start=0,
interval=1,
method='Dream.None')
# "expand" abstract stations
for node_id, node_data in data['nodes'].items():
if node_data['_class'] == 'Dream.AbstractCapacityStation':
# remove the node
new_data['nodes'].pop(node_id)
# remove outbound edges, while keeping a reference to the next station
# to set nextCapacityStationBufferId on the exit
next_abstract_station = None
for edge_id, (source, dest, edge_dict) in \
list(new_data['edges'].items()):
# list because we remove some elements in the loop
if source == node_id:
next_abstract_station = dest
del new_data['edges'][edge_id]
wip = []
for project, requirement_dict in required_capacity_by_project.items():
requirement = requirement_dict['%s_Station' % node_id]
name = '%s_%s_%s' % (project, node_id, requirement)
wip.append(
dict(_class='Dream.CapacityEntity',
id=name,
name=name,
capacityProjectId=project,
requiredCapacity=requirement))
new_data['nodes']["%s_Buffer" % node_id] = dict(
_class='Dream.CapacityStationBuffer',
id="%s_Buffer" % node_id,
name=node_data['name'],
wip=wip,
)
new_data['nodes']["%s_Station" % node_id] = dict(
_class='Dream.CapacityStation',
id="%s_Station" % node_id,
name=node_data['name'],
intervalCapacity=available_capacity_by_station[node_id],
)
exit = dict(_class='Dream.CapacityStationExit',
id="%s_Exit" % node_id,
name=node_data['name'],)
# set nextCapacityStationBufferId
if next_abstract_station:
exit['nextCapacityStationBufferId'] = '%s_Buffer' % next_abstract_station
new_data['nodes']["%s_Exit" % node_id] = exit
new_data['edges']['%s_1' % node_id] = [
"%s_Buffer" % node_id,
"%s_Station" % node_id,
{}]
new_data['edges']['%s_2' % node_id] = [
"%s_Station" % node_id,
"%s_Exit" % node_id,
{}]
return new_data
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment