reset_development_server.py 6.21 KB
Newer Older
1
"""Demo Data.
2

3
4
This script can be used to reset the demo data on the development server.
You need to have 'requests' installed!
5

6
CAREFUL: This script will delete everything existing!
7
8
"""

9
import sys
10
from random import randint, sample
11
from datetime import datetime as dt, timedelta
12
import requests
13

14

15
AMIVAPI_DEV_URL = "https://amiv-api.ethz.ch"
16
PVK_DEV_URL = 'http://pvk-api-dev.amiv.ethz.ch'
17

18
DATE_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
19
20
21
22
23
24
# Number of courses
MIN_CLOSED = 1
MAX_CLOSED = 3
MIN_OPEN = 2
MAX_OPEN = 4
# Spots per course
25
26
MIN_SPOTS = 20
MAX_SPOTS = 40
27
NUM_TIMESLOTS = 20  # limited number of unique timeslots to get overlap
28
29


30
31
32
33
34
35
36
37
def login(username, password):
    """Login user, return token."""
    data = {
        'username': username,
        'password': password,
    }
    return requests.post("%s/%s" % (AMIVAPI_DEV_URL, 'sessions'),
                         json=data).json()['token']
38
39


40
def post(resource, data, token):
41
    """Create something, ignoring auth."""
42
43
44
45
    response = requests.post('%s/%s' % (PVK_DEV_URL, resource),
                             json=data,
                             headers={'Authorization': token})
    data = response.json()
46

47
48
49
50
51
52
    if response.status_code != 201:
        status = data['_error']['code']
        message = str(data['_error'].get('message', ''))
        issues = str(data.get('_issues', ''))
        print('%s:' % status, issues or message)
        return {}
53

54
    return data
55
56


57
def create_lectures(department, token):
58
59
60
61
62
63
64
65
66
67
68
    """Create a few lectures, return names."""
    lectures = []
    for lecture in ['Some %s Lecture', 'Cool %s Lecture', 'Boring %s Lecture']:
        for year in range(1, 3):
            special_name = '%s Year %s' % (department.upper(), year)

            data = {
                'title': lecture % special_name,
                'year': year,
                'department': department,
            }
69
            response = post('lectures', data, token)
70
71
72
73
74
75
            if response:
                lectures.append(response['_id'])

    return lectures


76
77
78
79
80
81
82
83
84
85
86
87
88
def create_assistants(token):
    """Create a new assistant, yield _id."""
    i = 0
    while True:
        data = {
            'name': 'Pablo%s' % i,
            'email': 'pablo_%s@amiv.ethz.ch' % i,
        }
        response = post('assistants', data, token)
        yield response['_id']
        i += 1


89
90
91
92
93
94
95
96
def room_gen():
    """Produce rooms."""
    i = 0
    while True:
        yield "ETZ E %d" % i
        i += 1


97
98
99
def nethz_gen():
    """Produce nethz."""
    i = 0
100
    while True:
101
102
103
104
105
106
107
108
        yield "s%d" % i
        i += 1


def timeslots(starting_day):
    """Produce a stream of non-overlapping time ranges."""
    result = [];
    for _ in range(0, NUM_TIMESLOTS):
109
110
111
112
        year = starting_day.year
        month = starting_day.month
        day = starting_day.day

113
114
115
116
        # Random start and end time
        start = dt(year, month, day, randint(7, 10)).strftime(DATE_FORMAT)
        end = dt(year, month, day, randint(11, 14)).strftime(DATE_FORMAT)
        result.append({'start': start, 'end': end})
117
118
119
120

        # Only one slot per day to avoid overlap
        starting_day += timedelta(days=1)

121
122
    return result

123
124

ROOM = room_gen()
125
126
NETHZ = nethz_gen()
TIMESLOTS = timeslots(dt.now() + timedelta(days=90))  # Some time in the future
127
128


129
def create_course(lecture, assistant, token, open_signup=True):
130
131
132
133
134
135
136
137
138
139
140
141
142
143
    """Create several course for each lecture."""
    signup_diff = timedelta(days=-5) if open_signup else timedelta(15)
    start = dt.utcnow() + signup_diff
    end = start + timedelta(days=15)

    data = {
        'lecture': lecture,
        'assistant': assistant,

        'signup': {
            'start': start.strftime(DATE_FORMAT),
            'end': end.strftime(DATE_FORMAT),
        },

144
        'datetimes': sample(TIMESLOTS, randint(1, 3)),
145
146
147
        'room': next(ROOM),
        'spots': randint(MIN_SPOTS, MAX_SPOTS),
    }
148
149
150
    response = post('courses', data, token)

    return response
151
152


153
def create_signups(course, token):
154
    """Create random number of signups to a course."""
155
    for _ in range(randint(0, 2*MAX_SPOTS)):
156
        data = {
157
            'nethz': next(NETHZ),  # All different nethz to avoid overlap
158
            'course': course['_id'],
159
        }
160
        post('signups', data, token)
161
162


163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
def clear(resource, token):
    """ Remove every item."""
    while True:
        items = requests.get('%s/%s' % (PVK_DEV_URL, resource),
                             headers={'Authorization': token}).json()['_items']

        if not items:
            return  # Done!

        for item in items:
            item_url = '%s/%s/%s' % (PVK_DEV_URL, resource, item['_id'])
            res = requests.delete(item_url,
                                  headers={'Authorization': token,
                                           'If-Match': item['_etag']})
            if res.status_code != 204:
                print(res.json())


181
182
183
184
185
186
187
188
189
def main():
    """Login and create demo data."""
    if len(sys.argv) != 3:
        print('Usage: python %s USERNAME PASSWORD' % sys.argv[0])
        sys.exit(-1)

    print('Logging in...')
    token = login(sys.argv[1], sys.argv[2])

190
191
    # Order is important! some things can't be deleted before others
    print('Clearing existing data...')
192
193
    for res in ['payments', 'signups', 'courses', 'selections', 'lectures',
                'assistants']:
194
195
196
        print('Removing %s...' % res)
        clear(res, token)

197
198
199
200
    # Init generator for assistants
    assistants = create_assistants(token)

    # Create data
201
202
    # (Repeat for itet and mavt)
    for department in ['itet', 'mavt']:
203
        print('Department: %s' % department)
204

205
206
207
208
        print('Creating lectures...')
        lectures = create_lectures(department, token)

        print('Creating courses with closed signup...')
209
        for lecture in lectures:
210
211
            for _ in range(randint(MIN_CLOSED, MAX_CLOSED)):
                create_course(lecture, next(assistants),
212
                              token, open_signup=False)
213

214
        print('Creating courses with open signup...')
215
216
        courses = []
        for lecture in lectures:
217
218
            for _ in range(randint(MIN_OPEN, MAX_OPEN)):
                courses.append(create_course(lecture, next(assistants), token))
219

220
        print('Creating signups...')
221
        for course in courses:
222
223
            create_signups(course, token)

224

225
226
if __name__ == '__main__':
    main()