evaalapi demo

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#! /usr/bin/env -S python3 -O
#! /usr/bin/env -S python3

import os
import sys
import lzma
import requests
import time
from parse import parse
import yaml
from evaalapi import statefmt, estfmt

trialsdir = "trials/"
globinifn = "evaalapi.yaml"
server = "https://evaal.aaloa.org/evaalapi/"
trialname = "demo"

def do_req (req, n=2):
    r = requests.get(server+trialname+req)
    print("\n==>  GET " + req + " --> " + str(r.status_code))
    if False and r.headers['content-type'].startswith("application/x-xz"):
        l = lzma.decompress(r.content).decode('ascii').splitlines()
    else:
        l = r.text.splitlines()
    if len(l) <= 2*n+1:
        print(r.text + '\n')
    else:
        print('\n'.join(l[:n]
                        + ["   ... ___%d lines omitted___ ...   " % len(l)]
                        + l[-n:] + [""]))
    
    return(r)

def input_or_sleep (maxw):
    r = requests.get(server+trialname+"/state")
    s = parse(statefmt, r.text)
    trialts = s['trialts']
    rem = s['rem']
    if trialts > 0:
        print("Trial running, %.3f seconds to timeout" % rem)
    else:
        if trialts == 0:
            print("Trial not started")
        else:                           # trialts < 0
            print("Trial timed out %f seconds ago" % -rem)
        rem = 0
    if interactive:
        input("Press Enter to proceed\n")
    else:
        if rem > 0:
            w = min(maxw, max(0, rem-s['S']/2))
        else:
            w = maxw
        print("Waiting for %.1fs...\n" % w)
        time.sleep(w)
        
def demo (interactive, maxw):

    ## First of all, reload
    if reloadable:
        print("This is a reloadable trial, so let's start by reloading it to be sure")
        r = do_req("/reload")
        print("For official trials, this reload step must be skipped\n")

    ## Check initial state
    print("First, check the state of the trial")
    r = do_req("/state")
    print("The return code is the trial state, whose meaning is:")
    s = parse(statefmt, r.text); print(s.named)
    print("""'trialts' is 0, as expected
'rem' is -1, meaning that the trial has not started yet
'pos' is set to the initial position
""")

    ## Get first 1s worth of data
    input_or_sleep(maxw)
    print("""This is the first data we request, and we are at the start of trial,
where the position is known, so we do not bother sending a position estimate
and moreover we ask for a longer-than-usual horizon, that is, 1s""")
    r = do_req("/nextdata?horizon=1")

    ## Look at remaining time
    input_or_sleep(maxw)
    print("""You can freely intermix "state" requests in the flow of "nextdata"
requests.  This may be useful for consistency check, including timeout checks.  This is
possible by looking at the state of the trial:""")
    r = do_req("/state")
    print("The return code is the trial state, whose meaning is:")
    s = parse(statefmt, r.text); print(s.named)
    print("""'trialts' is 1.0, as expected
'rem' is the remaining time until timeout
""")
    
    ## Set estimates
    input_or_sleep(maxw)
    print("""From now on we keep sending an estimate and ask for new data
in steps of 0.5s.  Since this is the default horizon, we do not set horizon
explicitely in the request, but we only set the estimated position.
Note that the positions are just arbitrary numbers in this demo.""")
    for pos in range(5):
        r = do_req("/nextdata?position=%.1f,%.1f,%.1f" % (pos+.1, pos+.2, pos+.3))
        input_or_sleep(maxw)

    ## Get estimates
    print("""You can get the list of estimates set so far at any moment, even though this is mostly useful at the end of trial.  Here it is how it looks after setting 5 estimates:""")
    r = do_req("/estimates", 3)
    print("Parsing the last estimate line we get:")
    s = parse(estfmt, r.text.splitlines()[-1]); print(s.named)

    ## Get log
    input_or_sleep(maxw)
    print("""You can get a log of the trial session, including all received data.  Again, this is mostly useful at end of trial.  Here it is how it looks at this point:""")
    r = do_req("/log", 12)

    ## We finish here
    print("Demo stops here")

################################################################

if __name__ == '__main__':
    
    if len(sys.argv) == 1:
        print("""A demo for the EvAAL API.  Usage is
%s auto|interactive [trial] [server]

if omitted, TRIAL defaults to '%s' and SERVER to %s""" %
              (sys.argv[0], trialname, server))
        exit(1)
    elif sys.argv[1] == 'interactive':
        interactive = True
    elif sys.argv[1] == 'auto':
        interactive = False
    else:
        print("%s -- bad arguments: exiting" % sys.argv[0])
        exit(1)

    if len(sys.argv) > 2:
        trialname = sys.argv[2]

    if len(sys.argv) > 3:
        server = sys.argv[3]

    trialinifn = trialsdir + trialname + ".yaml"
    if os.path.isfile(trialinifn):
        with open(trialinifn, 'r') as inif:
            ini = yaml.safe_load(inif)
    elif os.path.isfile(globinifn):
        with open(globinifn, 'r') as inif:
            ini = yaml.safe_load(inif)
    else:
        print("%s -- no init file found: exiting" % sys.argv[0])
        exit(2)
    print(ini)
    global reloadable
    reloadable = bool(ini[trialname]['reloadable'])

    print("# Running %s demo test suite\n" % ("interactive" if interactive else "auto"))
    maxw = 3 if trialname == 'slowtest' else 10
    demo(interactive, maxw)
    exit(0)


# Local Variables:
# mode: python
# comment-column: 40
# fill-column: 100
# End: