mirror of
https://github.com/fazo96/pbs.git
synced 2025-01-26 14:24:20 +01:00
WIP async transformation of the library
This commit is contained in:
parent
265f3bc7f8
commit
6c6843df49
@ -22,6 +22,7 @@
|
||||
"bootstrap": "~3.3.4",
|
||||
"sweetalert": "~0.5.0",
|
||||
"angular": "~1.3.15",
|
||||
"angular-ui-router": "~0.2.13"
|
||||
"angular-ui-router": "~0.2.13",
|
||||
"async": "~0.9.2"
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ gulp.task('js',function(){
|
||||
jsFiles = ["src/*.js",
|
||||
"bower_components/jquery/dist/jquery.js",
|
||||
"bower_components/moment/moment.js",
|
||||
"bower_components/async/lib/async.js",
|
||||
"bower_components/bootstrap/dist/js/bootstrap.js",
|
||||
"bower_components/bootstrap/js/collapse.js",
|
||||
"bower_components/angular/angular.js",
|
||||
|
@ -1,6 +1,7 @@
|
||||
class PBS
|
||||
constructor: (@list, @verbose) ->
|
||||
@days = []
|
||||
@verbose = yes
|
||||
@criticalPaths = []
|
||||
|
||||
log: (x...) ->
|
||||
@ -25,68 +26,89 @@ class PBS
|
||||
return item
|
||||
|
||||
# Compute the item's end day
|
||||
calculateEndDay: (item) =>
|
||||
if !item.startDay?
|
||||
calculateEndDay: (item,cb) =>
|
||||
if item.endDay? then cb null, item.endDay
|
||||
else if !item.startDay?
|
||||
@log "calculating start day of",item.id
|
||||
item.startDay = @calculateStartDay item
|
||||
@log "start day of",item.id,"is",item.startDay
|
||||
item.endDay = item.startDay + item.duration
|
||||
@log "end day of",item.id,"is",item.endDay
|
||||
@insertDay item.endDay
|
||||
return item.endDay
|
||||
@calculateStartDay item, => @calculateEndDay item, cb
|
||||
else
|
||||
@log "start day of",item.id,"is",item.startDay
|
||||
item.endDay = item.startDay + item.duration
|
||||
@log "end day of",item.id,"is",item.endDay
|
||||
@insertDay item.endDay
|
||||
cb null, item.endDay
|
||||
|
||||
# Find out which day the activity starts
|
||||
calculateStartDay: (item) =>
|
||||
if !item.depends? or item.depends.length is 0
|
||||
calculateStartDay: (item,cb) =>
|
||||
if item.startDay? then cb null, item.startDay
|
||||
else if !item.depends? or item.depends.length is 0
|
||||
@insertDay 0
|
||||
return item.startDay = 0
|
||||
item.startDay = @maxa item.depends.map(@toActivity).map @calculateEndDay
|
||||
@log "start day of",item.id,"is",item.startDay
|
||||
# write max delay time to each depend
|
||||
for j,x of item.depends
|
||||
@log "checking permittedDelay to dependency", x, "of", item
|
||||
i = @toActivity x
|
||||
if !i.dependant? then i.dependant = [item.id]
|
||||
else i.dependant.push item.id
|
||||
if !i.permittedDelay?
|
||||
i.permittedDelay = item.startDay - @calculateEndDay i
|
||||
@log "written permittedDelay to dependency", x, "of", item, "as", i.permittedDelay
|
||||
else @log "aborting permittedDelay: already calculated"
|
||||
@log "permitted delay of",x,"is",i.permittedDelay
|
||||
@insertDay item.startDay
|
||||
return item.startDay
|
||||
cb null, item.startDay = 0
|
||||
else
|
||||
async.map item.depends.map(@toActivity), @calculateEndDay.bind(@), (er, r) =>
|
||||
item.startDay = @maxa r
|
||||
@log "start day of",item.id,"is",item.startDay
|
||||
# write max delay time to each depend
|
||||
checkPermittedDelay = (x,c) =>
|
||||
@log "checking permittedDelay to dependency", x, "of", item
|
||||
i = @toActivity x
|
||||
if !i.dependant? then i.dependant = [item.id]
|
||||
else i.dependant.push item.id
|
||||
if !i.permittedDelay?
|
||||
@calculateEndDay i, (e,d) =>
|
||||
i.permittedDelay = item.startDay - d
|
||||
@log "written permittedDelay to dependency", x, "of", item, "as", i.permittedDelay
|
||||
@log "permitted delay of",x,"is",i.permittedDelay
|
||||
c()
|
||||
else
|
||||
@log "aborting permittedDelay: already calculated"
|
||||
@log "permitted delay of",x,"is",i.permittedDelay
|
||||
c()
|
||||
async.each item.depends, checkPermittedDelay.bind(@), =>
|
||||
@insertDay item.startDay
|
||||
cb null, item.startDay
|
||||
|
||||
calculateDelays: (item) =>
|
||||
if !item.dependant? or item.dependant.length is 0 then return no
|
||||
lowestFDelay = 0; fDelay = no; cDelay = 0
|
||||
for j,i of item.dependant
|
||||
x = @toActivity i
|
||||
if !isNaN(x.permittedDelay) or x.permittedDelay < lowestFDelay or fDelay is no
|
||||
@log "activity", i, "dependant on", item.id, "has the lowest delay for now ("+(x.permittedDelay or 0)+")"
|
||||
lowestFDelay = x.permittedDelay or 0
|
||||
cDelay = x.chainedDelay or 0
|
||||
fDelay = yes
|
||||
olDelay = item.chainedDelay
|
||||
item.chainedDelay = lowestFDelay + cDelay
|
||||
@log "chained delay of", item.id, "is", item.chainedDelay
|
||||
return item.chainedDelay isnt olDelay
|
||||
calculateDelays: (item,cb) =>
|
||||
if !item.dependant? or item.dependant.length is 0 then cb null, no
|
||||
else
|
||||
lowestFDelay = 0; fDelay = no; cDelay = 0
|
||||
checkDependant = (i,c) =>
|
||||
x = @toActivity i
|
||||
if !isNaN(x.permittedDelay) or x.permittedDelay < lowestFDelay or fDelay is no
|
||||
@log "activity", i, "dependant on", item.id, "has the lowest delay for now ("+(x.permittedDelay or 0)+")"
|
||||
lowestFDelay = x.permittedDelay or 0
|
||||
cDelay = x.chainedDelay or 0
|
||||
fDelay = yes
|
||||
c()
|
||||
async.each item.dependant, checkDependant.bind(@), =>
|
||||
olDelay = item.chainedDelay
|
||||
item.chainedDelay = lowestFDelay + cDelay
|
||||
@log "chained delay of", item.id, "is", item.chainedDelay
|
||||
cb null, item.chainedDelay isnt olDelay
|
||||
|
||||
calculateCriticalPaths: (path) ->
|
||||
calculateCriticalPaths: (path,cb) ->
|
||||
@log "calculating path from",path
|
||||
lastID = path[path.length - 1]
|
||||
last = @toActivity lastID
|
||||
if last.dependant? and last.dependant.length > 0
|
||||
last.dependant.forEach (x) =>
|
||||
checkDependant = (x,cb2) =>
|
||||
ii = @toActivity x
|
||||
delay = ii.permittedDelay or 0
|
||||
if delay is 0
|
||||
@calculateCriticalPaths path.concat x
|
||||
cb2 null, yes
|
||||
@calculateCriticalPaths path.concat(x), cb
|
||||
else
|
||||
@log "dead end at", lastID, "-->", x, "because delay is", delay
|
||||
cb2 null, no
|
||||
async.each last.dependant, checkDependant.bind(@), (a,b) -> return
|
||||
else
|
||||
path.forEach (x) => @toActivity(x).critical = yes
|
||||
@log "calculated path", path
|
||||
@criticalPaths.push path
|
||||
setCritical = (x,c) =>
|
||||
@toActivity(x).critical = yes
|
||||
c null, yes
|
||||
async.each path, setCritical.bind(@), =>
|
||||
@log "calculated path", path
|
||||
@criticalPaths.push path
|
||||
cb null, path
|
||||
|
||||
# Find out which activity has the highest id
|
||||
highestID: => return @maxa(@list.map (x) -> x.id)
|
||||
@ -100,26 +122,41 @@ class PBS
|
||||
setData: (data) ->
|
||||
@list = data
|
||||
return @
|
||||
|
||||
|
||||
calculate: (options,cb) ->
|
||||
h = @highestID()
|
||||
for x,i in @list
|
||||
@log '('+x.id+'/'+h+')'
|
||||
@calculateEndDay x
|
||||
finished = no; i = 0
|
||||
while !finished
|
||||
i++; finished = yes
|
||||
for x,i in @list
|
||||
if @calculateDelays x
|
||||
finished = no
|
||||
@log "Done calculating delays. Took", i, "iterations"
|
||||
for x,i in @list
|
||||
if !x.depends? or x.depends.length is 0
|
||||
@calculateCriticalPaths [x.id]
|
||||
results = activities: @list, days: @days, criticalPaths: @criticalPaths
|
||||
if options?.json
|
||||
if cb? then cb(JSON.stringify results)
|
||||
JSON.stringify results
|
||||
else
|
||||
if cb? then cb(results)
|
||||
results
|
||||
@log "(Step 1) calculating startDay, endDay, freeDelay"
|
||||
async.each @list, @calculateEndDay.bind(@), =>
|
||||
@log "(Step 2) Starting chained delay calculations."
|
||||
cont = yes; i = 0
|
||||
notDone = ->
|
||||
console.log cont
|
||||
cont
|
||||
chainedDelayChanged = (x,res) =>
|
||||
i++
|
||||
cont = no
|
||||
@calculateDelays x, (e,r) =>
|
||||
@log "cDelay calc result:",r
|
||||
res null, r
|
||||
calculateAllDelays = (cb2) =>
|
||||
async.map @list, chainedDelayChanged, (err,r) ->
|
||||
iterator = (acc,x,cb3) ->
|
||||
if x
|
||||
cb3 null, yes
|
||||
else cb3 null, acc
|
||||
async.reduce r, no, iterator, (err,res) ->
|
||||
cont = res
|
||||
cb2 null
|
||||
#TODO: check WHILST
|
||||
async.whilst notDone, calculateAllDelays, =>
|
||||
@log "Done calculating delays. Took", i, "iterations"
|
||||
#TODO: check THIS vvvvv
|
||||
calculateCriticalPathIfApplicable = (x, c) =>
|
||||
if !x.depends? or x.depends.length is 0
|
||||
@calculateCriticalPaths [x.id], c
|
||||
async.each @list, calculateCriticalPathIfApplicable.bind(@), =>
|
||||
results = activities: @list, days: @days, criticalPaths: @criticalPaths
|
||||
@log "DONE:", results
|
||||
if options?.json
|
||||
cb JSON.stringify results
|
||||
else
|
||||
cb results
|
||||
|
@ -46,13 +46,15 @@ pertController = ($scope) ->
|
||||
localStorage.setItem 'ganttpert', sdata
|
||||
unless options.silent
|
||||
swal 'Ok', 'Data updated', 'success'
|
||||
$scope.pbs = new PBS(data).calculate()
|
||||
$scope.$broadcast 'dataChanged'
|
||||
$scope.pbs = new PBS(data).calculate {}, ->
|
||||
$scope.$broadcast 'dataChanged'
|
||||
catch e
|
||||
swal 'Error', e, 'error'
|
||||
|
||||
$scope.fromLocalStorage = (options) ->
|
||||
$scope.fromLocalStorage = (options,cb) ->
|
||||
options = options || {}
|
||||
if options.call? then cb = options
|
||||
else unless cb?.call? then return console.log "fromLocalStorage called without callback"
|
||||
data = localStorage.getItem options.name || 'ganttpert'
|
||||
if data is null then data = "[]"
|
||||
try
|
||||
@ -63,13 +65,15 @@ pertController = ($scope) ->
|
||||
swal 'JSON Error', e, 'error'
|
||||
if options.raw
|
||||
#console.log 'Loading: []'
|
||||
return []
|
||||
cb []
|
||||
else
|
||||
#console.log 'Loading: {list: [], days: []}'
|
||||
return list: [], days: []
|
||||
cb list: [], days: []
|
||||
if options.raw
|
||||
#console.log 'Loading: '+jdata
|
||||
return jdata
|
||||
cb jdata
|
||||
else
|
||||
#console.log 'Loading: '+$scope.pbs
|
||||
return $scope.pbs ?= new PBS(jdata).calculate()
|
||||
new PBS(jdata).calculate (x) ->
|
||||
$scope.pbs = x
|
||||
cb x
|
||||
|
@ -1,9 +1,8 @@
|
||||
pertApp.controller 'tableController', ($scope) ->
|
||||
$scope.list = []
|
||||
$scope.refreshTable = ->
|
||||
ls = $scope.fromLocalStorage()
|
||||
if ls?
|
||||
$scope.list = ls.activities
|
||||
$scope.fromLocalStorage (ls) ->
|
||||
if ls? then $scope.list = ls.activities
|
||||
$scope.$on 'dataChanged', $scope.refreshTable
|
||||
$scope.refreshTable()
|
||||
|
||||
@ -32,7 +31,7 @@ pertApp.controller 'pertDiagController', ($scope) ->
|
||||
network = new vis.Network (document.getElementById 'pertDiagram'), { nodes: nodes, edges: connections }, options
|
||||
$scope.rebuild = ->
|
||||
console.log 'rebuild'
|
||||
$scope.buildGraph $scope.fromLocalStorage()
|
||||
$scope.fromLocalStorage (r) -> $scope.buildGraph r
|
||||
$scope.$on 'dataChanged', $scope.rebuild
|
||||
$scope.rebuild()
|
||||
|
||||
@ -47,8 +46,8 @@ pertApp.controller 'ganttDiagController', ($scope) ->
|
||||
if !data? then return
|
||||
timeline = new vis.Timeline (document.getElementById 'timeline'), ($scope.toDates data.activities), {}
|
||||
$scope.$on 'dataChanged', ->
|
||||
$scope.buildTimeline $scope.fromLocalStorage()
|
||||
$scope.buildTimeline $scope.fromLocalStorage()
|
||||
$scope.fromLocalStorage (r) -> $scope.buildTimeline r
|
||||
$scope.fromLocalStorage (r) -> $scope.buildTimeline r
|
||||
|
||||
pertApp.controller 'rawEditorController', ($scope) ->
|
||||
$scope.reset = ->
|
||||
@ -60,10 +59,9 @@ pertApp.controller 'rawEditorController', ($scope) ->
|
||||
swal 'Invalid Data', e, 'error'
|
||||
$scope.toLocalStorage data
|
||||
$scope.reloadData = ->
|
||||
$scope.taData = JSON.stringify $scope.fromLocalStorage silent: yes, raw: yes
|
||||
$scope.$on 'dataChanged', ->
|
||||
$scope.reloadData()
|
||||
#$('#ta').val JSON.stringify $scope.fromLocalStorage silent: yes, raw: yes
|
||||
$scope.fromLocalStorage { silent: yes, raw: yes }, (x) ->
|
||||
$scope.taData = JSON.stringify x
|
||||
$scope.$on 'dataChanged', -> $scope.reloadData()
|
||||
$scope.reloadData()
|
||||
|
||||
pertApp.controller 'editorController', ($scope) ->
|
||||
@ -77,18 +75,18 @@ pertApp.controller 'editorController', ($scope) ->
|
||||
swal 'Ops', 'could not find '+id, 'warning'
|
||||
|
||||
$scope.delete = (index,id) ->
|
||||
newdata = $scope.fromLocalStorage raw: yes
|
||||
l = []
|
||||
if id? then for i,j of newdata
|
||||
if id isnt j.id
|
||||
l.push j
|
||||
else for i,j of newdata
|
||||
if parseInt(i) isnt index
|
||||
l.push j
|
||||
diff = newdata.length - l.length
|
||||
$scope.toLocalStorage l, silent: yes
|
||||
if diff isnt 1
|
||||
swal 'Done', diff+' item(s) deleted', 'warning'
|
||||
$scope.fromLocalStorage { raw: yes }, (newdata) ->
|
||||
l = []
|
||||
if id? then for i,j of newdata
|
||||
if id isnt j.id
|
||||
l.push j
|
||||
else for i,j of newdata
|
||||
if parseInt(i) isnt index
|
||||
l.push j
|
||||
diff = newdata.length - l.length
|
||||
$scope.toLocalStorage l, silent: yes
|
||||
if diff isnt 1
|
||||
swal 'Done', diff+' item(s) deleted', 'warning'
|
||||
|
||||
$scope.addNew = (id, dur, deps) ->
|
||||
dur ?= $('#new-duration').val().trim()
|
||||
@ -109,14 +107,14 @@ pertApp.controller 'editorController', ($scope) ->
|
||||
unless isNaN dep
|
||||
deps[i] = parseInt dep
|
||||
catch e
|
||||
newdata = $scope.fromLocalStorage silent: yes, raw: yes
|
||||
if !newdata? or newdata is null or !newdata.push?
|
||||
newdata = []
|
||||
newdata.push { id: id, duration: dur, depends: deps }
|
||||
$scope.toLocalStorage newdata, silent: yes
|
||||
$scope.fromLocalStorage { silent: yes, raw: yes }, (newdata) ->
|
||||
if !newdata? or newdata is null or !newdata.push?
|
||||
newdata = []
|
||||
newdata.push { id: id, duration: dur, depends: deps }
|
||||
$scope.toLocalStorage newdata, silent: yes
|
||||
|
||||
$scope.refreshEditor = ->
|
||||
data = $scope.fromLocalStorage { silent: yes, raw: yes }
|
||||
$scope.list = data || []
|
||||
$scope.fromLocalStorage { silent: yes, raw: yes }, (data) ->
|
||||
$scope.list = data || []
|
||||
$scope.$on 'dataChanged', $scope.refreshEditor
|
||||
$scope.refreshEditor()
|
||||
|
@ -9,6 +9,7 @@
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="stylesheet" href="sweet-alert.css">
|
||||
<script src="jquery.js"></script>
|
||||
<script src="async.js"></script>
|
||||
<script src="sweet-alert.js"></script>
|
||||
<script src="angular.js"></script>
|
||||
<script src="bootstrap.js"></script>
|
||||
|
Loading…
Reference in New Issue
Block a user