Preliminary recorder interface. Order is often wrong though
This commit is contained in:
parent
7007253072
commit
9f05bb644e
7 changed files with 118 additions and 17 deletions
|
@ -134,6 +134,8 @@ class CentralCommand(object):
|
||||||
'languages': self.config['languages'],
|
'languages': self.config['languages'],
|
||||||
'hugvey_ids': self.hugvey_ids,
|
'hugvey_ids': self.hugvey_ids,
|
||||||
'hugveys': [],
|
'hugveys': [],
|
||||||
|
'logbookId': None,
|
||||||
|
'logbook': [],
|
||||||
}
|
}
|
||||||
|
|
||||||
#use this to test if any threads stay open
|
#use this to test if any threads stay open
|
||||||
|
@ -143,6 +145,11 @@ class CentralCommand(object):
|
||||||
for hv_id in self.hugvey_ids:
|
for hv_id in self.hugvey_ids:
|
||||||
status['hugveys'].append(self.getHugveyStatus(hv_id, selected_id == hv_id))
|
status['hugveys'].append(self.getHugveyStatus(hv_id, selected_id == hv_id))
|
||||||
|
|
||||||
|
if selected_id and selected_id in self.hugveys:
|
||||||
|
if self.hugveys[selected_id].recorder:
|
||||||
|
status['logbook'] = self.hugveys[selected_id].recorder.currentLog
|
||||||
|
status['logbookId'] = selected_id
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def commandHugvey(self, hv_id, msg):
|
def commandHugvey(self, hv_id, msg):
|
||||||
|
|
|
@ -27,6 +27,7 @@ class Recorder:
|
||||||
self.main_folder = out_folder # unfortunately not every device plays 16kHz audio streams
|
self.main_folder = out_folder # unfortunately not every device plays 16kHz audio streams
|
||||||
self.running = False
|
self.running = False
|
||||||
self.data = array('h')
|
self.data = array('h')
|
||||||
|
self.currentLog = []
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
self.subsequentMutedFrames = 0
|
self.subsequentMutedFrames = 0
|
||||||
|
@ -34,6 +35,7 @@ class Recorder:
|
||||||
|
|
||||||
self.data = array('h')
|
self.data = array('h')
|
||||||
self.currentTranscription = ""
|
self.currentTranscription = ""
|
||||||
|
self.currentLog = []
|
||||||
|
|
||||||
t = time.strftime("%Y%m%d-%H:%M:%S")
|
t = time.strftime("%Y%m%d-%H:%M:%S")
|
||||||
|
|
||||||
|
@ -105,7 +107,8 @@ class Recorder:
|
||||||
def updateTranscription(self, text):
|
def updateTranscription(self, text):
|
||||||
self.currentTranscription = text
|
self.currentTranscription = text
|
||||||
|
|
||||||
def log(self, origin, msg):
|
def log(self, origin, msg, extra=None):
|
||||||
|
self.currentLog.append({'time':time.time(), 'origin': origin, 'msg': msg, 'extra': extra})
|
||||||
with open(os.path.join(self.out_folder, "log.txt"), "a") as fp:
|
with open(os.path.join(self.out_folder, "log.txt"), "a") as fp:
|
||||||
fp.write(f"{origin}: {msg}\n")
|
fp.write(f"{origin}: {msg}\n")
|
||||||
|
|
||||||
|
|
|
@ -251,6 +251,7 @@ class Condition(object):
|
||||||
self.method = None
|
self.method = None
|
||||||
self.type = None
|
self.type = None
|
||||||
self.vars = {}
|
self.vars = {}
|
||||||
|
self.logInfo = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def initFromJson(conditionClass, data, story):
|
def initFromJson(conditionClass, data, story):
|
||||||
|
@ -303,6 +304,7 @@ class Condition(object):
|
||||||
story.stats['silentTimeouts'] +=1
|
story.stats['silentTimeouts'] +=1
|
||||||
story.stats['consecutiveSilentTimeouts'] += 1
|
story.stats['consecutiveSilentTimeouts'] += 1
|
||||||
|
|
||||||
|
self.logInfo = "{}s".format(self.vars['seconds'])
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _hasVariable(self, story) -> bool:
|
def _hasVariable(self, story) -> bool:
|
||||||
|
@ -316,7 +318,10 @@ class Condition(object):
|
||||||
if 'notSet' in self.vars and self.vars['notSet']:
|
if 'notSet' in self.vars and self.vars['notSet']:
|
||||||
# inverse:
|
# inverse:
|
||||||
r = not r
|
r = not r
|
||||||
|
self.logInfo = "Does {} have variable {}".format(
|
||||||
|
'not' if 'notSet' in self.vars and self.vars['notSet'] else '',
|
||||||
|
self.vars['variable']
|
||||||
|
)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def _hasDiverged(self, story) -> bool:
|
def _hasDiverged(self, story) -> bool:
|
||||||
|
@ -335,6 +340,11 @@ class Condition(object):
|
||||||
# inverse:
|
# inverse:
|
||||||
r = not r
|
r = not r
|
||||||
|
|
||||||
|
self.logInfo = "Has {} diverged to {}".format(
|
||||||
|
'not' if 'inverseMatch' in self.vars and self.vars['inverseMatch'] else '',
|
||||||
|
self.vars['diversionId']
|
||||||
|
)
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def _hasMetReplyContains(self, story) -> bool:
|
def _hasMetReplyContains(self, story) -> bool:
|
||||||
|
@ -373,6 +383,10 @@ class Condition(object):
|
||||||
|
|
||||||
if 'instantMatch' in self.vars and self.vars['instantMatch']:
|
if 'instantMatch' in self.vars and self.vars['instantMatch']:
|
||||||
story.logger.info(f"Instant match on {self.vars['regex']}, {self.vars}")
|
story.logger.info(f"Instant match on {self.vars['regex']}, {self.vars}")
|
||||||
|
self.logInfo = "Instant match of {}, captured {}".format(
|
||||||
|
self.vars['regex'],
|
||||||
|
capturedVariables
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
# TODO: implement 'instant match' -> don't wait for isFinished()
|
# TODO: implement 'instant match' -> don't wait for isFinished()
|
||||||
|
|
||||||
|
@ -395,7 +409,11 @@ class Condition(object):
|
||||||
if capturedVariables is not None:
|
if capturedVariables is not None:
|
||||||
for captureGroup in capturedVariables:
|
for captureGroup in capturedVariables:
|
||||||
story.setVariableValue(captureGroup, capturedVariables[captureGroup])
|
story.setVariableValue(captureGroup, capturedVariables[captureGroup])
|
||||||
|
self.logInfo = "Match of {}, captured {} after, {}".format(
|
||||||
|
self.vars['regex'],
|
||||||
|
capturedVariables,
|
||||||
|
timeSinceReply
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
break # don't check other delays
|
break # don't check other delays
|
||||||
# wait for delay to match
|
# wait for delay to match
|
||||||
|
@ -408,6 +426,7 @@ class Condition(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# There is a match and no delay say, person finished speaking. Go ahead sir!
|
# There is a match and no delay say, person finished speaking. Go ahead sir!
|
||||||
|
self.logInfo = "Match"
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def getLogSummary(self):
|
def getLogSummary(self):
|
||||||
|
@ -1068,6 +1087,14 @@ class Story(object):
|
||||||
def addToLog(self, node):
|
def addToLog(self, node):
|
||||||
self.log.append((node, self.timer.getElapsed()))
|
self.log.append((node, self.timer.getElapsed()))
|
||||||
|
|
||||||
|
if self.hugvey.recorder:
|
||||||
|
if isinstance(node, Message):
|
||||||
|
self.hugvey.recorder.log('hugvey', node.text, node.id)
|
||||||
|
if isinstance(node, Diversion):
|
||||||
|
self.hugvey.recorder.log('diversion',node.id)
|
||||||
|
if isinstance(node, Condition):
|
||||||
|
self.hugvey.recorder.log('condition',node.logInfo, node.id)
|
||||||
|
|
||||||
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
|
||||||
|
@ -1143,8 +1170,6 @@ class Story(object):
|
||||||
message.id, message.text))
|
message.id, message.text))
|
||||||
self.addToLog(message)
|
self.addToLog(message)
|
||||||
self.hugvey.eventLogger.info(f"message: {message.id} {message.uuid} start \"{message.text}\"")
|
self.hugvey.eventLogger.info(f"message: {message.id} {message.uuid} start \"{message.text}\"")
|
||||||
if self.hugvey.recorder:
|
|
||||||
self.hugvey.recorder.log('h',message.text)
|
|
||||||
|
|
||||||
# TODO: prep events & timer etc.
|
# TODO: prep events & timer etc.
|
||||||
fn = await message.getAudioFilePath()
|
fn = await message.getAudioFilePath()
|
||||||
|
|
|
@ -59,6 +59,8 @@ img.icon {
|
||||||
width: 380px;
|
width: 380px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: scroll; }
|
overflow-y: scroll; }
|
||||||
|
.panopticon #status {
|
||||||
|
width: 50%; }
|
||||||
#status > div {
|
#status > div {
|
||||||
width: 33.3333333%;
|
width: 33.3333333%;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
|
@ -66,7 +68,7 @@ img.icon {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
position: relative; }
|
position: relative; }
|
||||||
#status > div#overview {
|
#status > div#overview {
|
||||||
width: 66.66667%; }
|
width: 100% / 3; }
|
||||||
#status .counts dd, #status .counts dt {
|
#status .counts dd, #status .counts dt {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
|
@ -80,7 +82,11 @@ img.icon {
|
||||||
color: white;
|
color: white;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center; }
|
justify-content: center;
|
||||||
|
width: 120px;
|
||||||
|
flex-grow: 1; }
|
||||||
|
.panopticon #status .hugvey {
|
||||||
|
width: 160px; }
|
||||||
#status .hugvey h1 {
|
#status .hugvey h1 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -304,3 +310,17 @@ body.showTimeline #toggleTimeline {
|
||||||
border-color: green; }
|
border-color: green; }
|
||||||
#timeline .vis-text, #timeline .vis-labelset .vis-label {
|
#timeline .vis-text, #timeline .vis-labelset .vis-label {
|
||||||
color: #999; }
|
color: #999; }
|
||||||
|
|
||||||
|
#logbook {
|
||||||
|
width: 50%;
|
||||||
|
padding: 10px;
|
||||||
|
color: #999; }
|
||||||
|
#logbook .log {
|
||||||
|
margin-bottom: 10px; }
|
||||||
|
#logbook .time {
|
||||||
|
color: #666; }
|
||||||
|
#logbook .content .origin {
|
||||||
|
padding-right: 10px;
|
||||||
|
color: orange; }
|
||||||
|
#logbook .content .extra {
|
||||||
|
color: #555; }
|
||||||
|
|
|
@ -13,6 +13,7 @@ class Panopticon {
|
||||||
languages: [],
|
languages: [],
|
||||||
hugveys: [],
|
hugveys: [],
|
||||||
selectedId: null,
|
selectedId: null,
|
||||||
|
logbook: "",
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
time_passed: function( hugvey, property ) {
|
time_passed: function( hugvey, property ) {
|
||||||
|
@ -21,6 +22,9 @@ class Panopticon {
|
||||||
timer: function(hugvey, property) {
|
timer: function(hugvey, property) {
|
||||||
return panopticon.stringToHHMMSS( hugvey[property] );
|
return panopticon.stringToHHMMSS( hugvey[property] );
|
||||||
},
|
},
|
||||||
|
formatted: function(time) {
|
||||||
|
return moment(time).utc().format("hh:mm:ss");
|
||||||
|
},
|
||||||
loadNarrative: function( code, file ) {
|
loadNarrative: function( code, file ) {
|
||||||
panopticon.hugveys.selectedId = null;
|
panopticon.hugveys.selectedId = null;
|
||||||
|
|
||||||
|
@ -58,6 +62,8 @@ class Panopticon {
|
||||||
},
|
},
|
||||||
showHugvey: function(hv) {
|
showHugvey: function(hv) {
|
||||||
panopticon.hugveys.selectedId = hv.language ? hv.id : null;
|
panopticon.hugveys.selectedId = hv.language ? hv.id : null;
|
||||||
|
panopticon.hugveys.logbook = [];
|
||||||
|
panopticon.hugveys.logbookId = null;
|
||||||
panopticon.updateSelectedHugvey();
|
panopticon.updateSelectedHugvey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,6 +115,8 @@ 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'];
|
||||||
|
this.hugveys.logbook = msg['logbook'];
|
||||||
|
this.hugveys.logbookId = msg['logbookId'];
|
||||||
if(this.hugveys.selectedId) {
|
if(this.hugveys.selectedId) {
|
||||||
this.updateSelectedHugvey();
|
this.updateSelectedHugvey();
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,13 +21,6 @@
|
||||||
<dd>{{uptime}}</dd>
|
<dd>{{uptime}}</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<ul id='languages'>
|
|
||||||
<li v-for="lang in languages" :title="lang.file"
|
|
||||||
:id="'lang-' + lang.code" class="btn lang--btn"
|
|
||||||
@click="loadNarrative(lang.code, lang.file)"><span
|
|
||||||
:class="['flag-icon', lang.code]"></span> {{lang.code}}</li>
|
|
||||||
</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]"
|
||||||
|
@ -68,10 +61,24 @@
|
||||||
<div class='btn' v-if="hv.status == 'running'" @click.stop="finish(hv)">Finish</div> <!-- to available state -->
|
<div class='btn' v-if="hv.status == 'running'" @click.stop="finish(hv)">Finish</div> <!-- to available state -->
|
||||||
<div class='btn' v-if="hv.status == 'running'" @click.stop="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.stop="resume(hv)">Resume</div>
|
<div class='btn' v-if="hv.status == 'paused'" @click.stop="resume(hv)">Resume</div>
|
||||||
|
<div class='light'>
|
||||||
|
{{ hv.light }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id='selectedHugvey'>
|
<div id='logbook'>
|
||||||
|
<div v-if="logbookId">
|
||||||
|
<h1>Log of {{logbookId}}</h1>
|
||||||
|
<div v-for="log in logbook" class='log'>
|
||||||
|
<div class='time'>{{formatted(log.time)}}</div>
|
||||||
|
<div class='content {{log.origin}}'>
|
||||||
|
<span class='origin'>{{log.origin}}</span>
|
||||||
|
<span class='msg'>{{log.msg}}</span>
|
||||||
|
<span v-if="log.extra" class='extra'>( {{log.extra}} )</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -82,6 +82,10 @@ img.icon{
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
|
||||||
|
.panopticon &{
|
||||||
|
width: 50%
|
||||||
|
}
|
||||||
|
|
||||||
& > div{
|
& > div{
|
||||||
width: 33.3333333%;
|
width: 33.3333333%;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
|
@ -90,7 +94,7 @@ img.icon{
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
&#overview{
|
&#overview{
|
||||||
width: 100% / 3 * 2;
|
width: 100% / 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,6 +117,12 @@ img.icon{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
width: 120px;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
.panopticon & {
|
||||||
|
width: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
h1{
|
h1{
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -492,3 +502,24 @@ img.icon{
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#logbook{
|
||||||
|
width: 50%;
|
||||||
|
padding: 10px;
|
||||||
|
color: #999;
|
||||||
|
.log{
|
||||||
|
margin-bottom:10px;
|
||||||
|
}
|
||||||
|
.time{
|
||||||
|
color:#666;
|
||||||
|
}
|
||||||
|
.content{
|
||||||
|
.origin{
|
||||||
|
padding-right: 10px;
|
||||||
|
color:orange;
|
||||||
|
}
|
||||||
|
.extra{
|
||||||
|
color:#555;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue