Passed
Push — main ( 20f858...b2f07a )
by Rahn20
01:07
created

main.Handler.charge_scooter()   A

Complexity

Conditions 1

Size

Total Lines 19
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
nop 1
dl 0
loc 19
rs 10
c 0
b 0
f 0
1
#!/usr/bin/python3
2
3
""" Main file for scooter program with Handler class. """
4
5
import sys
6
import inspect
7
import time
8
from threading import Thread
9
from datetime import datetime, timedelta
10
11
from src.api import ApiData
12
from src.scooter import Scooter
13
14
15
class Handler():
16
    """ Handler class """
17
18
    ## menu options
19
    _OPTIONS = {
20
        "1": "start_scooter",
21
        "2": "stop_running",
22
        "3": "get_scooter_info",
23
        "4": "return_scooter",
24
        "5": "charge_scooter",
25
    }
26
27
    ## scooter status
28
    _running = False
29
30
    ## Leave the scooter, stop the thread
31
    _return = False
32
33
    ## start renting time, a list of integers [H:M:S]
34
    _start_time = None
35
36
37
    def __init__(self) -> None:
38
        """ Initialize class """
39
        self.scooter = Scooter()
40
        self.api = ApiData(user_id = 1)   ## user id (random user)
41
42
        ## create a Thread
43
        self._thread = Thread(target=self.run, name="Move scooter")
44
45
46
    def _get_method(self, method_name):
47
        """ Uses function getattr() to dynamically get value of an attribute. """
48
        return getattr(self, self._OPTIONS[method_name])
49
50
51
    def _print_menu(self) -> None:
52
        """ Prints options for the program. """
53
        menu = ""
54
55
        for key in sorted(self._OPTIONS):
56
            method = self._get_method(key)
57
            docstring = inspect.getdoc(method)
58
59
            menu += "{choice}: {explanation}\n".format(
60
                choice = key,
61
                explanation = docstring
62
            )
63
64
        print(chr(27) + "[2J" + chr(27) + "[;H")
65
        print(menu)
66
67
68
    def run(self) -> None:
69
        """ Start a Thread. """
70
        while True:
71
            if self._return:
72
                break
73
            if self.scooter.check_scooter_in_city() is False:
74
                print("\nScooter is outside of the city")
75
                print("You can't use the scooter anymore. Press 4 to cancel the rental.")
76
77
                self.stop_running()
78
                time.sleep(10)
79
            elif self._running:
80
                self.battery_check()
81
                time.sleep(5)
82
83
84
    def battery_check(self) -> None:
85
        """ Check battery level, if battery < 20% print warning message and stop the scooter. """
86
        if self.scooter.check_battery():
87
            self.stop_running()
88
            print("\n\033[1;31m*\033[1;0m Low battery!! the scooter needs to be charged.")
89
        else:
90
            self.scooter.change_location()
91
            self.scooter.move_scooter()
92
93
            ## update API
94
            #self.api.update_scooter()
95
96
97
    def start_scooter(self) -> None:
98
        """ Move the scooter to a random location if battery > 20%. """
99
        if self.scooter.check_battery():
100
            print("\n\033[1;31m*\033[1;0m Low battery!! the scooter needs to be charged.")
101
            print("\nPress 4 to end the rental and leave the scooter at charging station.")
102
            print("Or you can press 5 to fully charge the scooter and end the rental.")
103
        else:
104
            self._running = True
105
106
107
    def stop_running(self) -> None:
108
        """ Stop the scooter. """
109
        if self._running is True:
110
            self._running = False
111
            self.scooter.stop_scooter()
112
113
            ## update API
114
            #self.api.update_scooter()
115
116
117
    def rental_time(self) -> timedelta:
118
        """ Returns the time the scooter has been rented by a user. """
119
        current = datetime.now().time().strftime("%H:%M:%S")
120
121
        current_time = timedelta(
122
            hours = int(current[0:2]),
123
            minutes = int(current[3:5]),
124
            seconds=int(current[6:8])
125
        )
126
127
        start_time = timedelta(
128
            hours = self._start_time[0],
129
            minutes = self._start_time[1],
130
            seconds = self._start_time[2]
131
        )
132
133
        return current_time - start_time
134
135
136
    def get_scooter_info(self) -> None:
137
        """ Get the scooter information. """
138
        if self._running:
139
            print("\nScooter is running.")
140
        else:
141
            print("\nScooter is in sleep mode.")
142
143
        print(self.scooter.__str__())
144
        print("Rent time: " + str(self.rental_time()))
145
146
147
    def charge_scooter(self):
148
        """Charge the scooter and end the rental. """
149
        ## Stop thread
150
        self._return = True
151
        self._running = False
152
        self._thread.join()
153
154
        ## Fully charges the battery and leave it at the charging Station
155
        #charging = self.api.get_station("Charging Station")
156
157
        self.scooter.data["battery"] = 100
158
        self.scooter.stop_scooter("available")
159
        #self.scooter.move_to_station(charging)
160
161
        ## update API
162
        #self.api.update_scooter()
163
        #self.api.update_log()
164
        #self.api.remove_user_connection()
165
        sys.exit()
166
167
168
    def return_scooter(self):
169
        """ Stop the rental and leave the scooter. """
170
        ## Stop thread
171
        self._return = True
172
        self._running = False
173
        self._thread.join()
174
        self.end_rental()
175
176
        #self.get_scooter_info()
177
        #print(self.scooter.data["status"])
178
179
        ## update API
180
        #self.api.update_scooter()
181
        #self.api.update_log()
182
        #self.api.remove_user_connection()
183
        sys.exit()
184
185
186
    def end_rental(self) -> None:
187
        """ Checks scooter's battery/maintenance/zone and stops the scooter. """
188
        if self.scooter.check_scooter_in_city() is False:
189
            self.scooter.stop_scooter("unavailable")
190
        elif self.scooter.check_battery():
191
            #charging = self.api.get_station("Charging Station")
192
193
            self.scooter.stop_scooter("charge")
194
            #self.scooter.move_to_station(charging)
195
        elif self.scooter.check_maintenance():
196
            #maintenance = self.api.get_station("Maintenance Station")
197
198
            self.scooter.stop_scooter("maintenance")
199
            #self.scooter.move_to_station(maintenance)
200
        else:
201
            self.scooter.stop_scooter("available")
202
203
204
    def rent_scooter(self):
205
        """ Print menu """
206
        while True:
207
            self._print_menu()
208
            choice = input("What do you want to do: ")
209
210
            try:
211
                self._get_method(choice.lower())()
212
            except KeyError:
213
                print("\nInvalid choice!")
214
215
            input("\nPress any key to continue ...")
216
217
218
    def main(self):
219
        """ Main method """
220
        try:
221
            print("\n************ Welcome to Scooter program **************\n")
222
223
            while True:
224
                scooter = int(input("Enter scooter id: "))
225
226
                if self.api.check_scooter_status(scooter):
227
                    current = datetime.now().time().strftime("%H:%M:%S")
228
                    self._start_time = [int(current[:2]), int(current[3:5]), int(current[6:8])]
229
                    break
230
231
                print("\n\033[1;31m*\033[1;0m Scooter is not available.\n")
232
233
            ## connect user and create log
234
            #self.api.connect_user()
235
            #self.api.create_log()
236
            #self.api.get_city_data()
237
238
            ## start a Thread
239
            self._thread.start()
240
            self.rent_scooter()
241
242
        except ValueError:
243
            print("\nScooter id must be a number.")
244
245
246
if __name__ == "__main__":
247
    Handler().main()
248