aboutsummaryrefslogtreecommitdiff
path: root/NeoRuntime/Runtime/luxcena_neo/neo_behaviour.py
blob: 9920ca441753ed5f5279c49ef94144c92b96a539 (plain) (blame)
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
import json
from os import path
from enum import Enum

class NeoBehaviour:
    """
    This is the base-class "main" should inherit from!
    All methods are blocking :) This means that you could potentially loose a "tick"
    For example, if "eachSecond" is taking up the thread, and the clock goes from 11:58 to 12:02, "eachHour", will not be called.
    """

    def __init__(self, package_path):
        """
        THIS METHOD SHOULD NOT BE OVERIDDEN! Use onStart if you want a setup-method!!!
        Contains basic setup 
        """
        self.vars = Variables(package_path)

    def declare_variables(self):
        """ This should be overridden, and ALL variables should be declared here. """
        return

    def on_start(self):
        """ This method will be run right after __init__ """
        return

    def each_tick(self):
        """ This method will be run every tick, that means every time the program has time """
        return

    def each_second(self):
        """ This method is called every second (on the clock), given that the thread is open """
        return

    def each_minute(self):
        """ This method is called every mintue (on the clock), given that the thread is open """
        return

    def each_hour(self):
        """ This method is called every whole hour (on the clock), given that the thread is open """
        return

    def each_day(self):
        """ This method is called every day at noon, given that the thread is open """
        return

class VariableType(Enum):
    TEXT = 1
    INT = 2
    RANGE = 3
    COLOR = 4

class Variables:

    def __init__(self, package_path):
        self.__vars = {}
        self.__vars_save_file = f"{package_path}/variables.json"
        self.__saved_variables = {}
        self.read_saved_variables()
    
    def __getattr__(self, name):
        if name in ["_Variables__vars", "_Variables__vars_save_file", "_Variables__saved_variables"]:
            return super(Variables, self).__getattr__(name)
        return self.__vars[name].value

    def __setattr__(self, name, value):
        if name in ["_Variables__vars", "_Variables__vars_save_file", "_Variables__saved_variables"]:
            super(Variables, self).__setattr__(name, value)
        elif type(value) == Variable:
            self.__vars[name] = value
        else:
            self.__vars[name].value = value
    
    def __delattr__(self, name):
        if name in ["_Variables__vars", "_Variables__vars_save_file", "_Variables__saved_variables"]:
            super(Variables, self).__delattr__(name)
        else:
            del self.__vars[name]

    def __getitem__(self, name):
        return self.__vars[name]

    def __setitem__(self, name, value):
        self.__vars[name].value = value
    
    def __contains__(self, name):
        return name in self.__vars
    
    def __repr__(self):
        return json.dumps({name: var.value for name, var in self.__vars.items()})
    
    def __str__(self):
        return repr(self)
    
    def __dir__(self):
        return super(Variables, self).__dir__() + [name for name in self.__vars.keys()]
    
    def __len__(self):
        return len(self.__vars)
    
    def __iter__(self):
        return iter(self.__vars.items())

    def declare(self, name: str, default: any, var_type: VariableType, on_change = None, **kwargs):
        """ Declare a new variable. """
        if name in self.__saved_variables:
            default = self.__saved_variables[name]
        var = Variable(self.save_variables, name, default, var_type, on_change, **kwargs)
        self.__setattr__(name, var)
    
    def read_saved_variables(self):
        """ Read saved variable values from file. """
        if not path.exists(self.__vars_save_file):  return
        try:
            with open(self.__vars_save_file, "r") as f:
                self.__saved_variables = json.load(f)
        except:
            print("Could not load saved variables")

    def save_variables(self):
        """ Save variable values to file. """
        self.__saved_variables = {name: var.value for name, var in self.__vars.items()}
        with open(self.__vars_save_file, "w") as f:
            f.write(json.dumps(self.__saved_variables))

class Variable:

    def __init__(self, save_func, key, default, var_type, on_change):
        self.__save_func = save_func
        self.__key = key
        self.__value = default
        self.__var_type = var_type
        self.__on_change = on_change
    
    @property
    def key(self): return self.__key

    @property
    def value(self): return self.__value

    @value.setter
    def value(self, value):
        self.__value = value
        self.__save_func()
        if self.__on_change is not None:
            self.__on_change(self.value)
    
    @property
    def var_type(self): return self.__var_type.name