Last active
February 16, 2021 19:00
-
-
Save robertbrook/b0d6dd21ed3c9dc28c93679b485c6dc0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# this code gets all routes and processes in whatever order they emerge from the database (randomly) | |
# in order to ensure routes are parsed correctly, we need to ensure that all inbound routes to a step are parsed before we parse the outbound route | |
# this means we need to start at the start step, acknowledging that some procedure maps have more than one start step | |
# in order to do this we need to ... | |
# hard code an array of start steps | |
# start step for PNSI: u7VOBBH0 | |
procedure.pnsi.start_steps = [u7VOBBH0] | |
# start steps for draft negative: wShvPQbP, j4iPxsxb | |
procedure.draft_negative.start_steps = [wShvPQbP, j4iPxsxb] | |
# start steps for made negative: wShvPQbP, j4iPxsxb | |
procedure.made_negative.start_steps = [wShvPQbP, j4iPxsxb] | |
# move this into procedure model alongside conclusion steps as part of step collection | |
# these routes will be returned unsorted | |
# get an array of routes in the procedure | |
routes = [] | |
for route in routes | |
# this will record whether the route is current or whether it ended in the past or starts in the future | |
# add a boolean attribute of current with value NULL | |
route.current = NULL | |
# this will record the state of the route as it's parsed, being NULL, TRUE, FALSE or UNTRAVERSABLE | |
# add a string attribute of status with value NULL | |
route.status = NULL | |
# this will record whether a route has been fully parsed or not | |
# routes being output from an AND or an OR step may need to be parsed more than once depending on the parse order | |
# it is possible therefore for a route to have a parsed state of not NULL but to still not be fully parsed | |
# all routes start unparsed - obviously | |
# add a boolean attribute of parsed with value FALSE | |
route.parsed = FALSE | |
end | |
# Looping through all the routes until all routes are parsed, remembering they are unsorted | |
for route in routes | |
if route.parsed == TRUE | |
log "parsed route", route | |
else | |
# which step does the route come from? | |
# this is 'fromStep' in the procedure model | |
# get the source step of the route | |
# check the type of the source step and process accordingly | |
# BUSINESS STEP | |
if route.source_step == business_step | |
# we expect a business step to have one and only one input | |
if route.source_step.inputs != 1 | |
log "unexpected number of inputs", route.source_step | |
else | |
# check if we're trying to parse a route before we have parsed the immediately preceding route | |
# because we're in a loop, this has the effect of all preceding routes needing to be parsed before the current route can be | |
if route.parsed = FALSE | |
# the default behaviour when trying to parse a route from a business step is to not parse if the immediately preceding route has not yet been parsed | |
if !(start_steps.include?(route.source_step)) | |
# do nothing with this route | |
# proceed - via the loop - to the next route in the array and attempt to parse that | |
# we will attempt to parse this route again on the next and subsequent loops | |
# we do not parse a route until all inbounds up the tree have been parsed | |
# this is a brute force, breadth first traversal | |
# which is a recursion explosion?!? | |
# exception for start steps to force the parsing to start | |
# otherwise if the step is in the array of start steps | |
# ignore the state and time boundedness of the inbound routes of start steps or no route will ever get parsed | |
# and we'd be stuck in an infinte loop | |
# this should, in theory, force us to traverse the graph from the start steps | |
# check whether the route we're parsing is current | |
# if it's not current ... | |
if (route.start_date > today) or (route.end_date < today) | |
route.status = UNTRAVERSABLE | |
route.current = FALSE | |
route.parsed = TRUE | |
# if the route we're parsing is current ... | |
elsif route.current == TRUE | |
route.current = TRUE | |
route.parsed = TRUE | |
if (route.source_step.actualised.past?) or (route.source_step.actualised == today) | |
route.status = TRUE | |
elsif (route.source_step.actualised.future?) or (no date) | |
route.status = NULL | |
elsif route.source_step.actualised == "" | |
route.status = NULL | |
end | |
end | |
end | |
# attempt to parse a route from a business step where the inbound route to that step has already been parsed | |
if input route.parsed == TRUE | |
route.parsed = TRUE | |
# if the route is not current | |
if (route.start_date > today) or (route.end_date < today) | |
route.status = UNTRAVERSABLE | |
route.current = FALSE | |
# if the route is current | |
elsif !(route.start_date > today) and !(route.end_date < today) | |
route.current = TRUE | |
if input route.value == UNTRAVERSABLE | |
# taint the roads off the bridge as closed if the bridge is closed | |
route.status = UNTRAVERSABLE | |
elsif input route.value != UNTRAVERSABLE | |
if (route.source_step.actualised.past?) or (route.source_step.actualised == today) | |
route.status = TRUE | |
elsif (route.source_step.actualised.future?) or (route.source_step.actualised == "") | |
route.status = NULL | |
# elsif (source step is not actualised) | |
elsif !(route.source_step == actualised) | |
route.status = NULL | |
end | |
end | |
end | |
end | |
end | |
# AND gate | |
elsif (route.source_step == "AND step") | |
if !(route.source_step is the target step for two routes) | |
log "unexpected number of inputs", route | |
elsif route.source_step is the target step of two routes | |
if both input routes to the route.source_step .parsed == TRUE | |
route.parsed = TRUE | |
if (route.start_date.future?) or (route.end_date.past?) | |
route.value = UNTRAVERSABLE | |
route.current = FALSE | |
elsif !(route.start_date.future?) and !(route.end_date.past?) | |
route.current = TRUE | |
# process as per AND gate logic | |
# https://ukparliament.github.io/ontologies/procedure/flowcharts/meta/design-notes/#truth-table-and | |
end | |
elsif (one input route to the source step has a parsed attribute of TRUE) and (the other has a parsed attribute of FALSE) | |
if (route.start_date.future?) or (route.end_date.past?) | |
route.value = UNTRAVERSABLE | |
route.current = FALSE | |
elsif !(route.start_date.future?) and !(route.end_date.past?) | |
route.current = TRUE | |
# process as per AND gate logic | |
# pass in the status attribute of the unparsed input route as NULL | |
# we're assuming that the unparsed input has a value of NULL until we return to this route with both inputs parsed | |
# this route will be reparsed once both inputs have been parsed | |
# https://ukparliament.github.io/ontologies/procedure/flowcharts/meta/design-notes/#truth-table-and | |
end | |
elsif both input routes to the source step .parsed == FALSE | |
# do nothing and pick up on next loop | |
# this is forcing traversal from the start | |
end | |
end | |
# OR gate | |
elsif (route.source_step == "OR step") | |
if the OR step is the target step for less than or more than two routes | |
log an error: unexpected number of inputs | |
elsif the source OR step is the target step of two routes | |
if both input routes to the source step have a parsed attribute of TRUE | |
route.parsed = TRUE | |
if (route.start_date > today) or (route.end_date < today) | |
route.value = UNTRAVERSABLE | |
route.current = FALSE | |
elsif !(route.start_date > today) and !(route.end_date < today) | |
route.current = TRUE | |
# process as per OR gate logic | |
# https://ukparliament.github.io/ontologies/procedure/flowcharts/meta/design-notes/#truth-table-or | |
end | |
elsif one input route to the source step has a parsed attribute of TRUE and the other has a parsed attribute of FALSE | |
if (route.start_date is greater than today) or (its end date is less than today) | |
route.value = UNTRAVERSABLE | |
route.current = FALSE | |
elsif the route's start date is not greater than today and its end date is not less than today | |
set the route current attribute to TRUE | |
# process as per OR gate logic | |
# pass in the status attribute of the unparsed input route as NULL | |
# we're assuming that the unparsed input has a value of NULL until we return to this route with both inputs parsed | |
# this route will be reparsed once both inputs have been parsed | |
# https://ukparliament.github.io/ontologies/procedure/flowcharts/meta/design-notes/#truth-table-or | |
end | |
elsif both input routes to the source step have a parsed attribute of FALSE | |
# do nothing and pick up on next loop | |
# this is forcing traversal from the start | |
end | |
end | |
# NOT gate | |
elsif (route.source_step == "NOT step") | |
if the NOT step is the target step for less than or more than one route | |
log an error: unexpected number of inputs | |
elsif the source NOT step is the target step of one route | |
if the input route parsed attribute is FALSE | |
# do nothing and pick up on next loop | |
# this is forcing traversal from the start | |
elsif the input route parsed attribute is TRUE | |
route.parsed = TRUE | |
if (route.start_date is greater than today) or (its end date is less than today) | |
route.value = UNTRAVERSABLE | |
route.current = FALSE | |
elsif (route.start_date is not greater than today) and (its end date is not less than today) | |
route.current = TRUE | |
# process as per NOT gate logic | |
# https://ukparliament.github.io/ontologies/procedure/flowcharts/meta/design-notes/#truth-table-not | |
end | |
end | |
end | |
# Decision step | |
elsif (route.source_step == "decision step") | |
if !(the decision step is the target step for one route) | |
log "unexpected number of inputs", route | |
elsif the source decision step is the target step of one route | |
if the input route .parsed == FALSE | |
# do nothing and pick up on next loop | |
# this is forcing traversal from the start | |
elsif the input route parsed == TRUE | |
route.parsed = TRUE | |
if (route.start_date.future?) or (route.end_date.past?) | |
route.value = UNTRAVERSABLE | |
route.current = FALSE | |
elsif !(route.start_date.future?) and !(route.end_date.past?) | |
route.current = TRUE | |
# process as per decision step logic | |
# htps://ukparliament.github.io/ontologies/procedure/flowcharts/meta/design-notes/#truth-table-decision | |
end | |
end | |
end | |
end | |
# END OF ROUTE PARSING | |
# having parsed the route and established its state, we can now look at the target step and, if it's a business step, set its potential state | |
get the target step of the route | |
if route.target_step is a business step | |
if route.value == TRUE | |
flag target business step as CAUSED TO BE ACTUALISED | |
elsif route.value == ALLOWS | |
flag the target step as ALLOWED TO BE ACTUALISED | |
# theoretically reachable given current procedural "rules" | |
# future potential state | |
# for example, a question on a fatal motion has not been put because no fatal motion has been tabled yet and may possibly never be | |
elsif (route.value == NULL) or (route.value == FALSE) | |
flag target step as NOT YET ACTUALISABLE | |
end | |
# not theoretically reachable given current procedural "rules" | |
# for example, EVEL standing order suspension | |
# the bridge is closed so steps on the far side cannot be reached unless the bridge opens | |
elsif route.value == UNTRAVERSABLE | |
flag target step as NOT NOW ACTUALISABLE | |
elsif the target step is a logic step or decision step | |
# do nothing and pick up on next loop | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment