Show progress for selected Hugvey

This commit is contained in:
Ruben van de Ven 2019-01-25 14:10:19 +01:00
parent 2a712fb7e1
commit d00b676ad8
6 changed files with 115 additions and 25 deletions

View file

@ -91,9 +91,9 @@ class CentralCommand(object):
status['status'] = hv.getStatus() status['status'] = hv.getStatus()
status['language'] = hv.language_code status['language'] = hv.language_code
status['msg'] = hv.story.currentMessage.id if hv.story.currentMessage else None status['msg'] = hv.story.currentMessage.id if hv.story.currentMessage else None
status['counts'] = hv.story.getStoryCounts()
status['finished'] = hv.story.isFinished() status['finished'] = hv.story.isFinished()
status['history'] = hv.story.getLogSummary()
status['counts'] = {t: len(a) for t, a in status['history'].items() }
return status return status

View file

@ -13,6 +13,7 @@ class Message(object):
self.text = text self.text = text
self.isStart = False self.isStart = False
self.reply = None self.reply = None
self.replyTime = None
self.audioFile= None self.audioFile= None
@classmethod @classmethod
@ -23,8 +24,9 @@ class Message(object):
msg.audioFile = data['audio']['file'] msg.audioFile = data['audio']['file']
return msg return msg
def setReply(self, text): def setReply(self, text, replyTime):
self.reply = text self.reply = text
self.replyTime = replyTime
def hasReply(self): def hasReply(self):
return self.reply is not None return self.reply is not None
@ -36,6 +38,13 @@ class Message(object):
return self.reply return self.reply
def getLogSummary(self):
return {
'id': self.id,
'time': self.replyTime,
'replyText': self.reply
}
class Condition(object): class Condition(object):
""" """
@ -98,6 +107,10 @@ class Condition(object):
return True return True
return self.vars['contains'] in story.currentMessage.getReply() return self.vars['contains'] in story.currentMessage.getReply()
def getLogSummary(self):
return {
'id': self.id
}
class Direction(object): class Direction(object):
""" """
@ -109,10 +122,14 @@ class Direction(object):
self.msgFrom = msgFrom self.msgFrom = msgFrom
self.msgTo = msgTo self.msgTo = msgTo
self.conditions = [] self.conditions = []
self.conditionMet = None
def addCondition(self, condition: Condition): def addCondition(self, condition: Condition):
self.conditions.append(condition) self.conditions.append(condition)
def setMetCondition(self, condition: Condition):
self.conditionMet = condition
@classmethod @classmethod
def initFromJson(direction, data, story): def initFromJson(direction, data, story):
msgFrom = story.get(data['source']) msgFrom = story.get(data['source'])
@ -124,6 +141,12 @@ class Direction(object):
direction.addCondition(c) direction.addCondition(c)
return direction return direction
def getLogSummary(self):
return {
'id': self.id,
'condition': self.conditionMet.id if self.conditionMet else None
}
class Diversion(object): class Diversion(object):
""" """
@ -147,6 +170,13 @@ class Diversion(object):
return diversion return diversion
def getLogSummary(self):
return {
'id': self.id,
# 'time': self.replyTime
}
storyClasses = { storyClasses = {
'Msg': Message, 'Msg': Message,
'Direction': Direction, 'Direction': Direction,
@ -224,18 +254,15 @@ class Story(object):
logger.debug('resume hugvey') logger.debug('resume hugvey')
self.timer.resume() self.timer.resume()
def getStoryCounts(self): def getLogSummary(self):
# counts = {} summary = {
# for item in self.log: # e[0]: the entity, e[1]: the logged time
# n =item.__class__.__name__ 'messages': [(e[0].getLogSummary(), e[1]) for e in self.log if isinstance(e[0], Message)],
# if n not in counts: 'directions': [(e[0].getLogSummary(), e[1]) for e in self.log if isinstance(e[0], Direction)],
# counts[n] = 0 'diversions': [(e[0].getLogSummary(), e[1]) for e in self.log if isinstance(e[0], Diversion)],
# counts[n] += 1
# return counts
return {
'messages': len([e for e in self.log if isinstance(e, Message)]),
'diversions': len([e for e in self.log if isinstance(e, Diversion)])
} }
# print(self.log)
return summary
def setStoryData(self, story_data): def setStoryData(self, story_data):
""" """
@ -347,7 +374,7 @@ class Story(object):
if e['is_final']: if e['is_final']:
# final result # final result
self.lastSpeechEndTime = e['time'] self.lastSpeechEndTime = e['time']
self.currentMessage.setReply(e['transcript']) self.currentMessage.setReply(e['transcript'], self.timer.getElapsed())
def _processDirections(self, directions): def _processDirections(self, directions):
for direction in directions: for direction in directions:
@ -355,11 +382,15 @@ class Story(object):
if condition.isMet(self): if condition.isMet(self):
logger.info("Condition is met: {0}, going to {1}".format( logger.info("Condition is met: {0}, going to {1}".format(
condition.id, direction.msgTo.id)) condition.id, direction.msgTo.id))
self.log.append(condition) direction.setMetCondition(condition)
self.log.append(direction) self.addToLog(condition)
self.addToLog(direction)
self.setCurrentMessage(direction.msgTo) self.setCurrentMessage(direction.msgTo)
return direction return direction
def addToLog(self, node):
self.log.append((node, self.timer.getElapsed()))
async def _renderer(self): async def _renderer(self):
""" """
every 1/10 sec. determine what needs to be done based on the current story state every 1/10 sec. determine what needs to be done based on the current story state
@ -400,7 +431,7 @@ class Story(object):
logger.info("Current message: ({0}) \"{1}\"".format( logger.info("Current message: ({0}) \"{1}\"".format(
message.id, message.text)) message.id, message.text))
self.log.append(message) self.addToLog(message)
# TODO: prep events & timer etc. # TODO: prep events & timer etc.
if message.audioFile: if message.audioFile:
self.hugvey.sendCommand({ self.hugvey.sendCommand({

View file

@ -101,6 +101,11 @@ img.icon {
cursor: grab; } cursor: grab; }
#story svg#graph:active { #story svg#graph:active {
cursor: grabbing; } cursor: grabbing; }
#story svg#graph .beenHit circle {
stroke: #0f0;
stroke-width: 2px; }
#story svg#graph line.beenHit {
stroke: #0f0; }
#story circle { #story circle {
cursor: pointer; cursor: pointer;
fill: #77618e; } fill: #77618e; }

View file

@ -28,7 +28,9 @@
</ul> </ul>
</div> </div>
<div class='hugvey' v-for="hv in hugveys" <div class='hugvey' v-for="hv in hugveys"
:class="[{'hugvey--on': hv.status != 'off'},'hugvey--' + hv.status]"> :class="[{'hugvey--on': hv.status != 'off'},'hugvey--' + hv.status]"
@click="showHugvey(hv)"
>
<h1> <h1>
{{ hv.id }} {{ hv.id }}
</h1> </h1>
@ -54,9 +56,9 @@
{{ hv.msg }} {{ hv.msg }}
</div> </div>
</div> </div>
<div class='btn' v-if="hv.status == 'running'" @click="pause(hv)">Pause</div> <div class='btn' v-if="hv.status == 'running'" @click.stop="pause(hv)">Pause</div>
<div class='btn' v-if="hv.status == 'paused'" @click="resume(hv)">Resume</div> <div class='btn' v-if="hv.status == 'paused'" @click.stop="resume(hv)">Resume</div>
<div class='btn' v-if="hv.status == 'finished'" @click="restart(hv)">Restart</div> <div class='btn' v-if="hv.status == 'finished'" @click.stop="restart(hv)">Restart</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -4,6 +4,7 @@ class Panopticon {
constructor() { constructor() {
console.log( "Init panopticon" ); console.log( "Init panopticon" );
this.languages = [] this.languages = []
this.selectedHugvey = null;
this.hugveys = new Vue( { this.hugveys = new Vue( {
el: "#status", el: "#status",
data: { data: {
@ -37,6 +38,10 @@ class Panopticon {
change_lang: function(hv, lang_code) { change_lang: function(hv, lang_code) {
hv.status = "loading"; hv.status = "loading";
return panopticon.change_language(hv.id, lang_code); return panopticon.change_language(hv.id, lang_code);
},
showHugvey: function(hv) {
panopticon.selectedHugvey = hv.id;
panopticon.updateSelectedHugvey();
} }
} }
} ); } );
@ -73,11 +78,35 @@ class Panopticon {
this.hugveys.languages = msg['languages']; this.hugveys.languages = msg['languages'];
this.languages = msg['languages']; this.languages = msg['languages'];
this.hugveys.hugveys = msg['hugveys']; this.hugveys.hugveys = msg['hugveys'];
if(this.selectedHugvey) {
this.updateSelectedHugvey();
}
break; break;
} }
} ); } );
} }
updateSelectedHugvey() {
if(! this.selectedHugvey) {
return;
}
console.log('showNOW', this.selectedHugvey);
let hv = this.getHugvey(this.selectedHugvey);
if(this.graph.language_code != hv.language) {
this.loadNarrative(hv.language);
}
this.graph.updateHugveyStatus(hv);
}
getHugvey(id) {
for(let hv of this.hugveys.hugveys) {
if(hv.id == id) {
return hv;
}
}
return null;
}
send( msg ) { send( msg ) {
if ( this.socket.readyState == WebSocket.OPEN ) { if ( this.socket.readyState == WebSocket.OPEN ) {
this.socket.send( JSON.stringify( msg ) ); this.socket.send( JSON.stringify( msg ) );
@ -129,10 +158,10 @@ class Panopticon {
this.send( { action: 'resume', hugvey: hv_id } ) this.send( { action: 'resume', hugvey: hv_id } )
} }
pause( hv_id ) { pause( hv_id ) {
this.send( { action: 'play', hugvey: hv_id } ) this.send( { action: 'pause', hugvey: hv_id } )
} }
restart( hv_id ) { restart( hv_id ) {
this.send( { action: 'restart', hugvey: hv_id } ) this.send( { action: 'restart', hugvey: hv_id } );
} }
change_language( hv_id, lang_code ) { change_language( hv_id, lang_code ) {
this.send( { action: 'change_language', hugvey: hv_id, lang_code: lang_code } ); this.send( { action: 'change_language', hugvey: hv_id, lang_code: lang_code } );
@ -718,6 +747,19 @@ class Graph {
this.saveState(); this.saveState();
} }
updateHugveyStatus(hv) {
let els = document.getElementsByClassName('beenHit');
while(els.length > 0) {
els[0].classList.remove('beenHit');
}
for(let msg of hv['history']['messages']) {
document.getElementById(msg[0]['id']).classList.add('beenHit');
}
for(let msg of hv['history']['directions']) {
document.getElementById(msg[0]['id']).classList.add('beenHit');
}
}
saveState() { saveState() {
window.localStorage.setItem( "lastState", this.getJsonString() ); window.localStorage.setItem( "lastState", this.getJsonString() );
} }

View file

@ -177,6 +177,16 @@ img.icon{
&:active{ &:active{
cursor: grabbing; cursor: grabbing;
} }
.beenHit{
circle {
stroke: #0f0;
stroke-width: 2px;
}
}
line.beenHit {
stroke: #0f0;
}
} }
circle{ circle{