mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
Compare commits
1488 Commits
O1.20.3-E1
...
upsilon-de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9b49e0c17 | ||
|
|
bcef91bb59 | ||
|
|
ff068ca797 | ||
|
|
9d8e78ca1e | ||
|
|
90efabb404 | ||
|
|
26ee665d50 | ||
|
|
2233ca341b | ||
|
|
677528dfb6 | ||
|
|
bd78483d82 | ||
|
|
2b5d6e9d7f | ||
|
|
9bf61ded07 | ||
|
|
e3938e355b | ||
|
|
076fa3ab81 | ||
|
|
be0edc48b6 | ||
|
|
d1b8cefcf9 | ||
|
|
81ced8662c | ||
|
|
c1f5b4afac | ||
|
|
18f979dffe | ||
|
|
3c1bf54f0b | ||
|
|
5eb8054cde | ||
|
|
f0f67b2766 | ||
|
|
c403aeaa04 | ||
|
|
0a119fbad1 | ||
|
|
be688a487d | ||
|
|
84fe92e3d7 | ||
|
|
96077fcfb6 | ||
|
|
3566d44df2 | ||
|
|
13902cae72 | ||
|
|
59db12e78e | ||
|
|
696747a9a0 | ||
|
|
7093f706ff | ||
|
|
cc4b008048 | ||
|
|
1b9b53a201 | ||
|
|
a1f598194c | ||
|
|
768bd52d46 | ||
|
|
818e4d281f | ||
|
|
f380c927f7 | ||
|
|
0fc06fafaf | ||
|
|
7a9a8ba371 | ||
|
|
e6f14741d6 | ||
|
|
6a83882826 | ||
|
|
34506d334c | ||
|
|
ee8d456f1e | ||
|
|
e971681dfd | ||
|
|
276e8a603a | ||
|
|
c1cc19d47c | ||
|
|
7f560f8a5b | ||
|
|
f7cd1693c9 | ||
|
|
e6a308891b | ||
|
|
0c3506d85d | ||
|
|
d6831e46bf | ||
|
|
b6d5bda120 | ||
|
|
4c26e846d3 | ||
|
|
219c6c4046 | ||
|
|
ea1e0c8140 | ||
|
|
7f5fc1269d | ||
|
|
deda7483e3 | ||
|
|
520b88e364 | ||
|
|
172f168bb2 | ||
|
|
89def884f7 | ||
|
|
d3513a0763 | ||
|
|
ff54918502 | ||
|
|
3b22656d4f | ||
|
|
16d1946934 | ||
|
|
ac71576acc | ||
|
|
891693abe2 | ||
|
|
cf3cec7442 | ||
|
|
e20b1dee07 | ||
|
|
8ff2e021ec | ||
|
|
43a96629a4 | ||
|
|
6748f12239 | ||
|
|
5e83c03f8d | ||
|
|
510143678f | ||
|
|
35799f9a0d | ||
|
|
46f7eb5afe | ||
|
|
2671b6e0e1 | ||
|
|
64b4012f90 | ||
|
|
2374fe4cf8 | ||
|
|
1953371266 | ||
|
|
b667509ab4 | ||
|
|
cb6fd76141 | ||
|
|
f7a298aa0b | ||
|
|
5b87721f6e | ||
|
|
d51c55fc6c | ||
|
|
52bc616cd2 | ||
|
|
458c9316f1 | ||
|
|
9ac62c0496 | ||
|
|
7f2ba08761 | ||
|
|
a5354f589a | ||
|
|
2bf46f59ce | ||
|
|
0f2ce293d1 | ||
|
|
764ff6fd86 | ||
|
|
a0583aa2a9 | ||
|
|
0cabec542d | ||
|
|
ab854e16ab | ||
|
|
fd159fe489 | ||
|
|
f89ffc9b00 | ||
|
|
51d5ed04d0 | ||
|
|
a945fc1025 | ||
|
|
6976e524ad | ||
|
|
4630052630 | ||
|
|
3c6641c808 | ||
|
|
45a9dda989 | ||
|
|
73450419bb | ||
|
|
a124ed72b5 | ||
|
|
b44a95a9b3 | ||
|
|
aadcd37f31 | ||
|
|
0916996121 | ||
|
|
b4820d52e4 | ||
|
|
a87a99af7a | ||
|
|
83d6d33edf | ||
|
|
1067216d4f | ||
|
|
c0d998017d | ||
|
|
a729ef2a4c | ||
|
|
b43d773051 | ||
|
|
4acc79f1c7 | ||
|
|
58a373e683 | ||
|
|
8041c7a9d0 | ||
|
|
c5960430a3 | ||
|
|
12d8eeeb2c | ||
|
|
224cec5efc | ||
|
|
7af7b895f5 | ||
|
|
0e65c97774 | ||
|
|
72d10f8396 | ||
|
|
7030c58c51 | ||
|
|
1a681c7c75 | ||
|
|
ed002ed14b | ||
|
|
2312147957 | ||
|
|
d7f54ad644 | ||
|
|
1de090cea4 | ||
|
|
81dc1bd806 | ||
|
|
fc95028b57 | ||
|
|
c9c868c32c | ||
|
|
8d6c7d1bff | ||
|
|
42d8fea8c6 | ||
|
|
2a89c23e07 | ||
|
|
62d4d59d6b | ||
|
|
1bf164e1e3 | ||
|
|
851ec2ab69 | ||
|
|
08eb1aec99 | ||
|
|
78b606e825 | ||
|
|
ea89bc9aa5 | ||
|
|
56ce3b0f42 | ||
|
|
57e4cbe402 | ||
|
|
dfb5b90e55 | ||
|
|
1d00d7d9d3 | ||
|
|
3a220c0507 | ||
|
|
1fbd5281a9 | ||
|
|
51a5f699c3 | ||
|
|
77167d1706 | ||
|
|
a1e213ac91 | ||
|
|
d87c67d35b | ||
|
|
99b070a30d | ||
|
|
2a234305f3 | ||
|
|
992fb5dc85 | ||
|
|
891afff4bb | ||
|
|
92c653f2f2 | ||
|
|
25d4793441 | ||
|
|
4893b73917 | ||
|
|
0b2a581177 | ||
|
|
391fd5e243 | ||
|
|
ba43135fcb | ||
|
|
4d5b37fab1 | ||
|
|
e8ea693e5c | ||
|
|
125e1a8a82 | ||
|
|
7dff05287d | ||
|
|
25cd0d44f3 | ||
|
|
0751c88a2d | ||
|
|
d983797ac8 | ||
|
|
1319ad2f42 | ||
|
|
741a71554d | ||
|
|
9588052d68 | ||
|
|
35017ec167 | ||
|
|
3b12f29815 | ||
|
|
1f91a5f900 | ||
|
|
c826e556a1 | ||
|
|
1db74c78ab | ||
|
|
71a8c20ee7 | ||
|
|
d8423fb4f1 | ||
|
|
5444bdae99 | ||
|
|
952a83400a | ||
|
|
8996f960dc | ||
|
|
e4718fcb95 | ||
|
|
19de87f9b5 | ||
|
|
5f51ed0628 | ||
|
|
e4f0762db3 | ||
|
|
cbec2e5883 | ||
|
|
1e0fa89efe | ||
|
|
363ffbcaf8 | ||
|
|
48587c15d7 | ||
|
|
3eaa116ec6 | ||
|
|
ab8b353c9c | ||
|
|
8e543f30c9 | ||
|
|
833bc4a120 | ||
|
|
a01f4bcf1a | ||
|
|
3e42d4847a | ||
|
|
2a6d110f2f | ||
|
|
2ee7b67af1 | ||
|
|
be3c8fce9c | ||
|
|
ec36325799 | ||
|
|
36fa4a4152 | ||
|
|
6758a95292 | ||
|
|
5be8d6a1f5 | ||
|
|
5220dda095 | ||
|
|
7c51b1e55d | ||
|
|
7a2ee2bc56 | ||
|
|
9f6d52d9d5 | ||
|
|
efb32c9612 | ||
|
|
caf23dcbab | ||
|
|
6a894997fc | ||
|
|
f348d9eb5d | ||
|
|
0e0dc4a9c2 | ||
|
|
2be1a6e5a9 | ||
|
|
adab2c223b | ||
|
|
745099842a | ||
|
|
39f33347f9 | ||
|
|
03ae762b4a | ||
|
|
5b7bdc1ec1 | ||
|
|
7d61e236df | ||
|
|
7f8e6a6b87 | ||
|
|
9c69379096 | ||
|
|
aff5803ef3 | ||
|
|
fd7bdc7345 | ||
|
|
807945ad0f | ||
|
|
35f09ed389 | ||
|
|
c73b13bd41 | ||
|
|
47558446c4 | ||
|
|
45b4dd337c | ||
|
|
0332f43c5c | ||
|
|
667bac136b | ||
|
|
b15d49511d | ||
|
|
04ae526a39 | ||
|
|
0e49d23faa | ||
|
|
595c69bfcf | ||
|
|
18ff283580 | ||
|
|
42368ecd6e | ||
|
|
27cf6a0615 | ||
|
|
5ed8aef907 | ||
|
|
3c53421ffa | ||
|
|
d10d1cd65d | ||
|
|
cec75bfaed | ||
|
|
77352e34b5 | ||
|
|
38796253cb | ||
|
|
4b7631e78a | ||
|
|
c54a97a03d | ||
|
|
d42e4269a9 | ||
|
|
2bf6de5044 | ||
|
|
22ba190542 | ||
|
|
0e24823511 | ||
|
|
f174fbc3f5 | ||
|
|
4ca7d9208c | ||
|
|
2bfc243e5a | ||
|
|
add333b920 | ||
|
|
eeff886cc1 | ||
|
|
ff307b8df8 | ||
|
|
21f08a2d06 | ||
|
|
c837709801 | ||
|
|
a0caf67d7c | ||
|
|
f4e84bc208 | ||
|
|
225b942989 | ||
|
|
3b955c2eb6 | ||
|
|
0e46954f80 | ||
|
|
bf1d570623 | ||
|
|
5f50f3fc9c | ||
|
|
4a830a0f30 | ||
|
|
01c3f767e4 | ||
|
|
3c098b684b | ||
|
|
e886863230 | ||
|
|
7ce3aac2f6 | ||
|
|
3c26035feb | ||
|
|
ff40b8b862 | ||
|
|
62e98107f7 | ||
|
|
7a6c211001 | ||
|
|
80f099c274 | ||
|
|
d3754a931a | ||
|
|
3af3d70055 | ||
|
|
8db051474c | ||
|
|
3328bc28b9 | ||
|
|
c65b1c6d3c | ||
|
|
15801ae9e4 | ||
|
|
3dfc8d749c | ||
|
|
9f7aba4593 | ||
|
|
5365718761 | ||
|
|
c0c1615f14 | ||
|
|
a770ee919b | ||
|
|
7e64124ddc | ||
|
|
e2598031c8 | ||
|
|
2ebc1bc22f | ||
|
|
202c273c67 | ||
|
|
45229b80cd | ||
|
|
b675a78a87 | ||
|
|
15f0833f3b | ||
|
|
e40d63a6ff | ||
|
|
323eba63e1 | ||
|
|
3b293c822a | ||
|
|
8ac969d772 | ||
|
|
865bacf89a | ||
|
|
841ac7d5f4 | ||
|
|
c92c4d8383 | ||
|
|
97a168052b | ||
|
|
42343d562c | ||
|
|
3740a93a9f | ||
|
|
6dc31401fe | ||
|
|
8c3378a723 | ||
|
|
126bdd68bb | ||
|
|
f1c24db90a | ||
|
|
fd4a2205f3 | ||
|
|
fc252672cc | ||
|
|
1c918f549c | ||
|
|
72a25ec26d | ||
|
|
bdfae184e9 | ||
|
|
23936a0c63 | ||
|
|
209428ca9d | ||
|
|
370eb14a04 | ||
|
|
bf8f8bcb27 | ||
|
|
fc3941511f | ||
|
|
9fda743de9 | ||
|
|
74ef528845 | ||
|
|
7a2721c979 | ||
|
|
227ca616ca | ||
|
|
1c04949336 | ||
|
|
93099ad808 | ||
|
|
88b4e904c0 | ||
|
|
dee783065b | ||
|
|
5a7b076ebe | ||
|
|
85ef57f7ed | ||
|
|
63c2b99260 | ||
|
|
377f4eee0c | ||
|
|
a63cbcf0c2 | ||
|
|
f2c17121d2 | ||
|
|
d16808183b | ||
|
|
6eabe9acae | ||
|
|
e1dcbad18a | ||
|
|
4fe84a4959 | ||
|
|
272797f31f | ||
|
|
c635f4e2b9 | ||
|
|
c8ba2fd268 | ||
|
|
3a391261c7 | ||
|
|
2da1610b27 | ||
|
|
5e130cc4f2 | ||
|
|
2b5a773993 | ||
|
|
19e5562228 | ||
|
|
9edf026110 | ||
|
|
ffb4c39e04 | ||
|
|
61673cd1b5 | ||
|
|
f95f9ebb2d | ||
|
|
23af100ed5 | ||
|
|
c7516f1464 | ||
|
|
23a94b7f50 | ||
|
|
af5f9ea578 | ||
|
|
f3d632c462 | ||
|
|
893a2a550d | ||
|
|
2443fa7d57 | ||
|
|
4f0f41be56 | ||
|
|
5eb0598107 | ||
|
|
43b56f3a89 | ||
|
|
034fc65bc2 | ||
|
|
9ab3e6c715 | ||
|
|
d8f93709b8 | ||
|
|
708070c284 | ||
|
|
9632b59b67 | ||
|
|
a0afbe9916 | ||
|
|
100917f29f | ||
|
|
814e2dee06 | ||
|
|
1a546e011b | ||
|
|
1faac23ee8 | ||
|
|
38614a849f | ||
|
|
24205a7e03 | ||
|
|
f4ce415e32 | ||
|
|
169fb7404e | ||
|
|
e575ffc7ce | ||
|
|
f591816122 | ||
|
|
cbbe7ef6ac | ||
|
|
f862cb023a | ||
|
|
f296778014 | ||
|
|
16eaab3b52 | ||
|
|
77707cd930 | ||
|
|
a3e2c9732f | ||
|
|
98c919db88 | ||
|
|
8126e0da7e | ||
|
|
685e73c52d | ||
|
|
64a90422c4 | ||
|
|
fea588bd9d | ||
|
|
9595ed1570 | ||
|
|
4f63100195 | ||
|
|
ed06b4e48b | ||
|
|
d5dbb8df6f | ||
|
|
fdef2b5d6e | ||
|
|
7fc28f8b72 | ||
|
|
2248e415c4 | ||
|
|
1da537479f | ||
|
|
0860e48cb6 | ||
|
|
70b162e63b | ||
|
|
398e974ccd | ||
|
|
d57e19ae70 | ||
|
|
87a5dc354d | ||
|
|
cd3f5225bb | ||
|
|
139ef4a052 | ||
|
|
66afb977db | ||
|
|
cb9dc38fa9 | ||
|
|
67e42aaac3 | ||
|
|
f1be48bdb1 | ||
|
|
ed5cff15c6 | ||
|
|
963647d59f | ||
|
|
a14f2015cf | ||
|
|
dbbf27e59b | ||
|
|
65b3a2857f | ||
|
|
dd48235721 | ||
|
|
46041e8e9a | ||
|
|
38faecda29 | ||
|
|
0bd30ed2e6 | ||
|
|
5cbce3c116 | ||
|
|
665de51bae | ||
|
|
47e3036afd | ||
|
|
1df3ef87e6 | ||
|
|
4222137549 | ||
|
|
806b11b589 | ||
|
|
fb4b2ffdfa | ||
|
|
d2ec87d9fd | ||
|
|
6b12d1aebf | ||
|
|
9afb42716d | ||
|
|
2d4c0f18d0 | ||
|
|
918c9249db | ||
|
|
cf33f84106 | ||
|
|
df7b97bb87 | ||
|
|
e8a1bc6149 | ||
|
|
b304a2ff7d | ||
|
|
50ee8021f3 | ||
|
|
ed7e0bd915 | ||
|
|
84d88a3e8d | ||
|
|
00b5d4b9fe | ||
|
|
2aee07ae55 | ||
|
|
41b2b64d80 | ||
|
|
473b0bbfcb | ||
|
|
58ef8cb95d | ||
|
|
5dce215165 | ||
|
|
f2f44f0f6f | ||
|
|
fbe542e5bf | ||
|
|
0a1b3bcaee | ||
|
|
f6e937a927 | ||
|
|
c4ed8f84d3 | ||
|
|
8e1b311be0 | ||
|
|
89e51166e7 | ||
|
|
e4961563e9 | ||
|
|
e72b0f633e | ||
|
|
0550b66c03 | ||
|
|
e41910e2f8 | ||
|
|
d91ae29607 | ||
|
|
3b90969b42 | ||
|
|
bd207cb845 | ||
|
|
917ba7ce83 | ||
|
|
9c9758fcb6 | ||
|
|
83ce9d5e86 | ||
|
|
d4f0c7d3e8 | ||
|
|
2837b240e9 | ||
|
|
0906dc919b | ||
|
|
9cda9d9e59 | ||
|
|
553f3fc682 | ||
|
|
9fdedecbff | ||
|
|
83c63a7011 | ||
|
|
9636964cb9 | ||
|
|
69d6ad5205 | ||
|
|
f9a123cc08 | ||
|
|
56f735e302 | ||
|
|
0a5e9e0889 | ||
|
|
8c949d7048 | ||
|
|
2f7edc5024 | ||
|
|
cd40938b26 | ||
|
|
0b54bf13f4 | ||
|
|
f5f11c6478 | ||
|
|
efda561425 | ||
|
|
15c96cefa6 | ||
|
|
400d03ebdb | ||
|
|
6f48adde7d | ||
|
|
3a573b1204 | ||
|
|
48598296cf | ||
|
|
a54d60644f | ||
|
|
d579e9d14c | ||
|
|
db0ae2f7a0 | ||
|
|
2a66fbb75d | ||
|
|
feb94af827 | ||
|
|
0b564510e7 | ||
|
|
05227184a1 | ||
|
|
e551c69d06 | ||
|
|
37c7b85da8 | ||
|
|
0bed38576a | ||
|
|
7c02c9e72f | ||
|
|
a5584634e5 | ||
|
|
62e5b3e135 | ||
|
|
62f43f393d | ||
|
|
3318780d7d | ||
|
|
a9fc3b7850 | ||
|
|
959efdc995 | ||
|
|
fa278b0d78 | ||
|
|
e8044f938e | ||
|
|
02f4f6fe74 | ||
|
|
fe973b0535 | ||
|
|
71a764277f | ||
|
|
f6379d16fd | ||
|
|
2156ca7e42 | ||
|
|
2f3339dff7 | ||
|
|
48a0da8a95 | ||
|
|
3460e9ffd8 | ||
|
|
1487acbe38 | ||
|
|
367f64dac8 | ||
|
|
19ee32986f | ||
|
|
7f0b8170d4 | ||
|
|
bba7408e6c | ||
|
|
838ee83a8c | ||
|
|
74c500df01 | ||
|
|
98b665ac4b | ||
|
|
0f4502ebce | ||
|
|
9eb81a6daf | ||
|
|
a15c682e3e | ||
|
|
74635f8d88 | ||
|
|
ebe6a7cc5f | ||
|
|
3a4e33a1a7 | ||
|
|
dd757969f3 | ||
|
|
0df76f1680 | ||
|
|
788e75eb4a | ||
|
|
7b4a94296b | ||
|
|
86511cc59d | ||
|
|
d90af0323e | ||
|
|
c0739b0e06 | ||
|
|
210a83b04d | ||
|
|
fb4fc4862d | ||
|
|
74c6bea8f8 | ||
|
|
7c1dc4d5c3 | ||
|
|
eb02fb5baa | ||
|
|
6fcab3952f | ||
|
|
5a6dfd8a20 | ||
|
|
c8afdcacab | ||
|
|
ef45fab63d | ||
|
|
0366c4cd00 | ||
|
|
dc8a1d48d9 | ||
|
|
649f48919e | ||
|
|
c3b752d6cc | ||
|
|
c5ca1e916a | ||
|
|
24f3ccf007 | ||
|
|
25b74ea2f8 | ||
|
|
0e7db3ce8a | ||
|
|
786a3273da | ||
|
|
ed54927c5b | ||
|
|
2ee86ce52f | ||
|
|
a3720d3d76 | ||
|
|
837fcd9bcc | ||
|
|
b0befbdbc5 | ||
|
|
cf9142b5a2 | ||
|
|
80587f35f1 | ||
|
|
ba94c7db00 | ||
|
|
4c29b05b53 | ||
|
|
85f8f4fedd | ||
|
|
e62c328661 | ||
|
|
080ac51aae | ||
|
|
bf5f24f96c | ||
|
|
7e24502414 | ||
|
|
dd45419006 | ||
|
|
aba2388253 | ||
|
|
5fca77a8f8 | ||
|
|
f258da16f1 | ||
|
|
35e4146551 | ||
|
|
76dad83aec | ||
|
|
f999c796c3 | ||
|
|
f86c22f10b | ||
|
|
c841362a63 | ||
|
|
33ad74e1be | ||
|
|
e4aa82e62a | ||
|
|
f40fe27b68 | ||
|
|
3e071a59fe | ||
|
|
f50f22081c | ||
|
|
313b5ed222 | ||
|
|
f8798aa561 | ||
|
|
46acd4eb61 | ||
|
|
018ea07796 | ||
|
|
d7f41e306c | ||
|
|
029dc2be5e | ||
|
|
bf99a2976b | ||
|
|
03c85c0b0e | ||
|
|
bd0c7de2bf | ||
|
|
08f351fe31 | ||
|
|
0282104086 | ||
|
|
ed95b46c5b | ||
|
|
b8727bc256 | ||
|
|
5ccf8d6b97 | ||
|
|
b80daf70d3 | ||
|
|
36655f1c19 | ||
|
|
ed18f1e95f | ||
|
|
cbb435d656 | ||
|
|
00b74430cd | ||
|
|
8705ddaf8a | ||
|
|
ddae6607f9 | ||
|
|
c4ef2016ba | ||
|
|
524a7d9619 | ||
|
|
e456667d5e | ||
|
|
3000431f3b | ||
|
|
50a32b470d | ||
|
|
3746354f26 | ||
|
|
8fae36bcd3 | ||
|
|
9e9c088e9e | ||
|
|
a635ecf59b | ||
|
|
a6ae1957d1 | ||
|
|
3686f819d6 | ||
|
|
382c303bd2 | ||
|
|
402858739e | ||
|
|
192794e299 | ||
|
|
6f797833b2 | ||
|
|
44d745eff3 | ||
|
|
4e7a846540 | ||
|
|
a35fb141c4 | ||
|
|
58602544e2 | ||
|
|
4242c77d64 | ||
|
|
58ff19858f | ||
|
|
f1d15022aa | ||
|
|
fc3986f65a | ||
|
|
b795834c63 | ||
|
|
9c8112658e | ||
|
|
ed86abebde | ||
|
|
671321db10 | ||
|
|
3ccd7d0fb7 | ||
|
|
4f34cd17a1 | ||
|
|
5cd22c9429 | ||
|
|
893539b76e | ||
|
|
b2e2f3c5a6 | ||
|
|
48ec836129 | ||
|
|
3d320b2768 | ||
|
|
134456267b | ||
|
|
d2df42bc35 | ||
|
|
20d7094352 | ||
|
|
d95b50abef | ||
|
|
ed03aae9ed | ||
|
|
32f567c60a | ||
|
|
83e6fc9579 | ||
|
|
73585d9f48 | ||
|
|
8a400b7871 | ||
|
|
297fbd3c00 | ||
|
|
ece6aa5f27 | ||
|
|
8feb8e3ea2 | ||
|
|
7b57f31fbf | ||
|
|
6b8db108d2 | ||
|
|
cf8ecfb438 | ||
|
|
5605515fa1 | ||
|
|
30cfa022d1 | ||
|
|
23f3407267 | ||
|
|
1006b951b9 | ||
|
|
43b7f767ee | ||
|
|
eb0ca7b118 | ||
|
|
0cdfc44c6f | ||
|
|
2ebff40c62 | ||
|
|
c66db8c98d | ||
|
|
a6b13185ab | ||
|
|
e8956f4293 | ||
|
|
36a40faaaf | ||
|
|
2554ec666e | ||
|
|
1aac2a1d4d | ||
|
|
32d591317b | ||
|
|
2703f9a506 | ||
|
|
497e4890b1 | ||
|
|
6c389c9a1d | ||
|
|
699cf22023 | ||
|
|
543d3d540e | ||
|
|
2f2e45a6a5 | ||
|
|
a834c954b8 | ||
|
|
2bee7eb267 | ||
|
|
6d18c33068 | ||
|
|
8242113641 | ||
|
|
7c8c7f79f6 | ||
|
|
f578c24af1 | ||
|
|
8059821025 | ||
|
|
b32497da23 | ||
|
|
c3c7651ca8 | ||
|
|
e8f1ea6aa5 | ||
|
|
ba3109e47a | ||
|
|
c2f8bbaf3c | ||
|
|
0587e41b3c | ||
|
|
ab1df4fbef | ||
|
|
a4213dcca8 | ||
|
|
2cf6f15dde | ||
|
|
f37008d8d7 | ||
|
|
3740e0f135 | ||
|
|
cb3a6694a5 | ||
|
|
cba596dde7 | ||
|
|
11f2b92e5d | ||
|
|
a69fc679a9 | ||
|
|
f4905c59a2 | ||
|
|
22b6990e63 | ||
|
|
09a7b9daca | ||
|
|
0116dc2e07 | ||
|
|
37b8c56b3d | ||
|
|
1a4cb3ad37 | ||
|
|
d4984722cf | ||
|
|
cbc3951ab1 | ||
|
|
62aafa7597 | ||
|
|
baf8b8cbf0 | ||
|
|
90b25ecf51 | ||
|
|
d02ce2dd16 | ||
|
|
79985a0199 | ||
|
|
f10cd19616 | ||
|
|
945a7b8d56 | ||
|
|
784234690c | ||
|
|
fd0284756f | ||
|
|
ca6a0bdcb6 | ||
|
|
35c4c7fa2e | ||
|
|
b08f793776 | ||
|
|
9f380bf424 | ||
|
|
d7f7bbe862 | ||
|
|
4718ff8016 | ||
|
|
a25ebc516a | ||
|
|
cabc1a9564 | ||
|
|
acd80f06ed | ||
|
|
c988233b84 | ||
|
|
b3bba17306 | ||
|
|
668bd6ba48 | ||
|
|
af1be64644 | ||
|
|
ea71a83143 | ||
|
|
30f1d8464c | ||
|
|
6072307e34 | ||
|
|
4926e273ed | ||
|
|
27ea26b03f | ||
|
|
f274b34939 | ||
|
|
9eff895a95 | ||
|
|
6e7cf88e3f | ||
|
|
ba6ee3f1b9 | ||
|
|
41554caf27 | ||
|
|
0a807c3b69 | ||
|
|
73017819ac | ||
|
|
d0e0ee610c | ||
|
|
a540ef8153 | ||
|
|
a77028a36b | ||
|
|
1838024934 | ||
|
|
0250ad8520 | ||
|
|
fcc803d7c5 | ||
|
|
d83e712256 | ||
|
|
7c51ab2130 | ||
|
|
6628b54218 | ||
|
|
6f3cb70f64 | ||
|
|
77ec00bc50 | ||
|
|
085c90353d | ||
|
|
b09da48748 | ||
|
|
ef3682b904 | ||
|
|
135a56b6b3 | ||
|
|
491c873c90 | ||
|
|
f6c9bb23c6 | ||
|
|
17284985f7 | ||
|
|
76e1bf8822 | ||
|
|
540c87c71f | ||
|
|
391904900a | ||
|
|
763ce87d14 | ||
|
|
37f78c5d4d | ||
|
|
4f2ea99c85 | ||
|
|
bef8719ce0 | ||
|
|
ba64458660 | ||
|
|
a60d47bd2e | ||
|
|
875b7b3734 | ||
|
|
9773c09eba | ||
|
|
fda0848036 | ||
|
|
7733378bdc | ||
|
|
3e3a6347a6 | ||
|
|
3227e7ca8a | ||
|
|
51ef7d7404 | ||
|
|
da3c4a48d0 | ||
|
|
ec0e72fcb8 | ||
|
|
8a45b3d552 | ||
|
|
d35e93901c | ||
|
|
8f380adc4f | ||
|
|
61a015b6f1 | ||
|
|
aa51661aa7 | ||
|
|
73172f8d0c | ||
|
|
5a20d914df | ||
|
|
05e6fbbcca | ||
|
|
66ea24584c | ||
|
|
859976423f | ||
|
|
f052ad7bf8 | ||
|
|
61646ccabc | ||
|
|
116cbf7df4 | ||
|
|
1354b3e4f3 | ||
|
|
5e91b12836 | ||
|
|
3b74553ed7 | ||
|
|
44fc94469e | ||
|
|
40b81313cb | ||
|
|
0c01ccb13e | ||
|
|
71449239c8 | ||
|
|
917e753426 | ||
|
|
134f1da4b0 | ||
|
|
0a3754aa23 | ||
|
|
cb9f9e0e40 | ||
|
|
11f41a97d4 | ||
|
|
738a477b66 | ||
|
|
9b17d1b882 | ||
|
|
11ef4bd996 | ||
|
|
ed2d5e3b2d | ||
|
|
49b74fb475 | ||
|
|
e8887a4e70 | ||
|
|
5e7d93b331 | ||
|
|
83722342f7 | ||
|
|
a42208f773 | ||
|
|
9f0c7a87fd | ||
|
|
990c45b661 | ||
|
|
5b106f091d | ||
|
|
878685b83c | ||
|
|
abefc800d9 | ||
|
|
89c50509d8 | ||
|
|
89107da1ae | ||
|
|
d022231a3a | ||
|
|
f449db62c3 | ||
|
|
7a6c0e6e7d | ||
|
|
f6c91f7dbe | ||
|
|
4209f0a26c | ||
|
|
d26ba0250b | ||
|
|
48d93584e7 | ||
|
|
fff514d410 | ||
|
|
5ce5f4fbac | ||
|
|
ea4770fc81 | ||
|
|
e09bd0a18c | ||
|
|
7146eff7ee | ||
|
|
5bc9579db6 | ||
|
|
e9c953fd6e | ||
|
|
02d7a02a93 | ||
|
|
9b3f7edfcd | ||
|
|
fa523c25c9 | ||
|
|
1939293cd2 | ||
|
|
60f875220e | ||
|
|
24456780e6 | ||
|
|
af3b2d4de4 | ||
|
|
479f34502f | ||
|
|
10c296e671 | ||
|
|
b7bbb258a8 | ||
|
|
7646f13ca8 | ||
|
|
56a6917cfd | ||
|
|
efbbbe94ff | ||
|
|
c7b758f536 | ||
|
|
890592854a | ||
|
|
6c6f8b581c | ||
|
|
f202a4f902 | ||
|
|
78cb340065 | ||
|
|
6e318593ae | ||
|
|
79e59f525e | ||
|
|
94b2da8e60 | ||
|
|
185c780215 | ||
|
|
35bfb8ec16 | ||
|
|
625a89e610 | ||
|
|
3cdb076c2c | ||
|
|
71070ee052 | ||
|
|
c28a5198d6 | ||
|
|
a08e3e1024 | ||
|
|
357db4493d | ||
|
|
e17ff842b5 | ||
|
|
d0f40f0177 | ||
|
|
fe4e2e3e9d | ||
|
|
c3ceb0074f | ||
|
|
0f95b579a4 | ||
|
|
55f21f127c | ||
|
|
89979b4f50 | ||
|
|
71be09b4e7 | ||
|
|
ffebd2e987 | ||
|
|
1f8ab10ae5 | ||
|
|
8726bbda3e | ||
|
|
072fdda6b8 | ||
|
|
316d054935 | ||
|
|
f3b770cb29 | ||
|
|
a9aeae94df | ||
|
|
1e7babadb8 | ||
|
|
7f63daa28e | ||
|
|
b1da6031c6 | ||
|
|
c89a7bc496 | ||
|
|
a8858023ba | ||
|
|
ff220b7103 | ||
|
|
6e9195fafa | ||
|
|
bd302bb67b | ||
|
|
7ae03975cc | ||
|
|
76eb155ed5 | ||
|
|
3f6e4444a5 | ||
|
|
92ee632ce2 | ||
|
|
1a47207bee | ||
|
|
1f0a18f94c | ||
|
|
a113801ec2 | ||
|
|
64208a7f3c | ||
|
|
f329ca825f | ||
|
|
f54c5a8172 | ||
|
|
8cd3fe679f | ||
|
|
636e863323 | ||
|
|
b69f06b772 | ||
|
|
1531f96bb8 | ||
|
|
764d14fed1 | ||
|
|
a178c88e54 | ||
|
|
591f47d6a9 | ||
|
|
937979503a | ||
|
|
3501146e35 | ||
|
|
48bd7b6a77 | ||
|
|
f09f06d7ac | ||
|
|
9775953142 | ||
|
|
71ac56f8a7 | ||
|
|
e295e9ead0 | ||
|
|
36742789b0 | ||
|
|
312c02fd69 | ||
|
|
bd22c06d98 | ||
|
|
b343c5a02c | ||
|
|
1f05547437 | ||
|
|
68397ad0a6 | ||
|
|
f0ecb4c833 | ||
|
|
5bbba6cf80 | ||
|
|
7f488b45f1 | ||
|
|
ff029ea785 | ||
|
|
1347b1a20c | ||
|
|
1fd970fe50 | ||
|
|
e9662e4c45 | ||
|
|
72e8ac7d02 | ||
|
|
06d7104776 | ||
|
|
1025fd9937 | ||
|
|
c55eb6b028 | ||
|
|
2ba1941270 | ||
|
|
ddfde60982 | ||
|
|
746a781016 | ||
|
|
fdcccde996 | ||
|
|
4869383263 | ||
|
|
229865aff8 | ||
|
|
291b400595 | ||
|
|
adf28345b1 | ||
|
|
a418602763 | ||
|
|
ca9cb63909 | ||
|
|
540209f1a9 | ||
|
|
e4162976e4 | ||
|
|
cfc37f1bac | ||
|
|
387d3c9aa1 | ||
|
|
b08a29cab4 | ||
|
|
110f333122 | ||
|
|
4aa19ccd78 | ||
|
|
56e03aae0c | ||
|
|
5e679b7bc8 | ||
|
|
bd5cdb0f65 | ||
|
|
99e63ec30b | ||
|
|
962136ce8f | ||
|
|
5eaea62073 | ||
|
|
3e2b5178ed | ||
|
|
3ac3fba468 | ||
|
|
0de5c89d9b | ||
|
|
d8527b02ad | ||
|
|
522456677a | ||
|
|
c0413709b7 | ||
|
|
cb54e22272 | ||
|
|
bee8d8531b | ||
|
|
5b21c57e4c | ||
|
|
0ecfa0012c | ||
|
|
0c44deb35f | ||
|
|
323e72a50c | ||
|
|
7184202a6e | ||
|
|
62e2a71da1 | ||
|
|
76beed20da | ||
|
|
86985a4aef | ||
|
|
aacd1a6f32 | ||
|
|
dd258a7975 | ||
|
|
04b2683af2 | ||
|
|
73b5b0775a | ||
|
|
a0497d3bd7 | ||
|
|
41778433b1 | ||
|
|
b4e9ceed18 | ||
|
|
c37b4bd1f4 | ||
|
|
83b4d9390d | ||
|
|
3252bad547 | ||
|
|
ea3e3287dc | ||
|
|
4233f197d3 | ||
|
|
a0acdc171b | ||
|
|
80f3af389f | ||
|
|
0dcb4e9aff | ||
|
|
6c508d9c29 | ||
|
|
f42b7e4b20 | ||
|
|
4df996cfd2 | ||
|
|
5df60e946a | ||
|
|
3a0796d3c5 | ||
|
|
d7f83eca1c | ||
|
|
6e0528deac | ||
|
|
78beafe3f1 | ||
|
|
d789e8da97 | ||
|
|
50bc31fcfa | ||
|
|
e00cb91f74 | ||
|
|
f96e4e92ce | ||
|
|
5f34d07e53 | ||
|
|
7acec88006 | ||
|
|
5afdec00b8 | ||
|
|
d9b5acc70d | ||
|
|
55615c10e3 | ||
|
|
cca750a1c4 | ||
|
|
7030159530 | ||
|
|
4f9c37e96b | ||
|
|
7f6a3f0fc1 | ||
|
|
95aa47625c | ||
|
|
c7711b74c2 | ||
|
|
a7b55776d6 | ||
|
|
c5beb6fdd2 | ||
|
|
5e83bee589 | ||
|
|
cf2cbd109e | ||
|
|
4cc3542a99 | ||
|
|
7142f9545e | ||
|
|
f8b3156f19 | ||
|
|
644cf4dcf3 | ||
|
|
75dc415e27 | ||
|
|
58867b66ca | ||
|
|
291941f4e2 | ||
|
|
547b4b2d71 | ||
|
|
bf79d4e438 | ||
|
|
fbf38f891d | ||
|
|
6f21310e08 | ||
|
|
993de56d59 | ||
|
|
0185e0562c | ||
|
|
d5e810f2b8 | ||
|
|
8dc6391e92 | ||
|
|
fe950386a0 | ||
|
|
9e9033537c | ||
|
|
ad7890a19c | ||
|
|
f789bb156d | ||
|
|
aa50a5eb7c | ||
|
|
eb5f4b333a | ||
|
|
8bb0b47b9f | ||
|
|
f66bde6d31 | ||
|
|
010b474f77 | ||
|
|
b9c34ace3a | ||
|
|
6ba88921b9 | ||
|
|
42f20fb58d | ||
|
|
61d33be2a7 | ||
|
|
4a3f749cc6 | ||
|
|
b2945c3f8b | ||
|
|
98499f6c9f | ||
|
|
58114255e5 | ||
|
|
9d077c672d | ||
|
|
0d883bfb19 | ||
|
|
aba09e1a1f | ||
|
|
3b24f9c2c3 | ||
|
|
5a5955b513 | ||
|
|
82a77df088 | ||
|
|
f2ba5daab9 | ||
|
|
f58633b03c | ||
|
|
b2d7ee800a | ||
|
|
a922e44558 | ||
|
|
cab22fcbce | ||
|
|
aadf8f5716 | ||
|
|
b0b6fe33c9 | ||
|
|
4ea8263185 | ||
|
|
8181753553 | ||
|
|
96b8e1859a | ||
|
|
65156c8e5a | ||
|
|
93b5a3f63a | ||
|
|
82c4fe2190 | ||
|
|
3a90ed6109 | ||
|
|
2740056472 | ||
|
|
81616950f3 | ||
|
|
6628e76d36 | ||
|
|
52adea0c1f | ||
|
|
14e2f6247a | ||
|
|
bb8a28ade0 | ||
|
|
3f25a37cc8 | ||
|
|
2f97dab6d1 | ||
|
|
a76e54642c | ||
|
|
194cd0491c | ||
|
|
29f47124b1 | ||
|
|
3a87e47de5 | ||
|
|
0e4de43b8f | ||
|
|
f491be2db5 | ||
|
|
31e694f41a | ||
|
|
9c320185dd | ||
|
|
c647bfe566 | ||
|
|
91e1154bb8 | ||
|
|
6f8d80f8ae | ||
|
|
c4cd3ecffa | ||
|
|
b10be2c60c | ||
|
|
71e7070657 | ||
|
|
3ba4f974f7 | ||
|
|
958b172d08 | ||
|
|
20cbefad41 | ||
|
|
0a6ac0b40b | ||
|
|
1bfeeb5842 | ||
|
|
8ce9f363ad | ||
|
|
482ca10363 | ||
|
|
190568ea84 | ||
|
|
16707aa518 | ||
|
|
6be5e7d62c | ||
|
|
8572f4953c | ||
|
|
81e425eb04 | ||
|
|
09c061e871 | ||
|
|
a525c35ebb | ||
|
|
88ea32bd0d | ||
|
|
43f50b7b2d | ||
|
|
bcb4b3095b | ||
|
|
f54b15b9c8 | ||
|
|
5d9c7b0c1f | ||
|
|
29714b401e | ||
|
|
d642339963 | ||
|
|
403315f6ac | ||
|
|
08c96c5107 | ||
|
|
c4aad1641e | ||
|
|
0465cec924 | ||
|
|
ad6edffc07 | ||
|
|
07c52139b9 | ||
|
|
26754a3230 | ||
|
|
7322751453 | ||
|
|
0f1e27b2b6 | ||
|
|
1d4d56a7dd | ||
|
|
f0cd0694a6 | ||
|
|
bf76b56f90 | ||
|
|
43d21180bc | ||
|
|
5c67f92d18 | ||
|
|
cc22b0d298 | ||
|
|
e2725c8e61 | ||
|
|
13d1b7077c | ||
|
|
8970e294aa | ||
|
|
1a5661fd4c | ||
|
|
5a07db3452 | ||
|
|
d2b36be846 | ||
|
|
7499a9e0a4 | ||
|
|
5339d9e7b4 | ||
|
|
4acbf3346b | ||
|
|
ebe207d67d | ||
|
|
b567a09103 | ||
|
|
ad80c2c4d7 | ||
|
|
697f727429 | ||
|
|
3705ce4f92 | ||
|
|
150a5bfa5a | ||
|
|
bd23135198 | ||
|
|
91dc5eb5ec | ||
|
|
bf95b460c3 | ||
|
|
86d0c19293 | ||
|
|
bf0f6c7a33 | ||
|
|
f64a650ef6 | ||
|
|
8f117e9d4e | ||
|
|
8a5ed92a56 | ||
|
|
59b2a64830 | ||
|
|
25ab4b2a52 | ||
|
|
b051242f2b | ||
|
|
a326a1f9ff | ||
|
|
d224778330 | ||
|
|
fa9c9c1567 | ||
|
|
e517128a9e | ||
|
|
3f43504398 | ||
|
|
ab864d10d8 | ||
|
|
d8e6b63a2e | ||
|
|
7168188a44 | ||
|
|
388d1a785e | ||
|
|
64ff5b4c70 | ||
|
|
5b4fc6ff84 | ||
|
|
d6751e6e03 | ||
|
|
5d3069ff34 | ||
|
|
c1b0465ca4 | ||
|
|
bad0c81bf0 | ||
|
|
2e2845370a | ||
|
|
6105f44a46 | ||
|
|
f777cad3f7 | ||
|
|
0c1d0195cd | ||
|
|
bc7ca057a0 | ||
|
|
10f8e2f507 | ||
|
|
ddbe76fec5 | ||
|
|
4e771fdb54 | ||
|
|
d862d5503c | ||
|
|
4ba0603e0c | ||
|
|
4d0950fa1e | ||
|
|
ac2dd9cdf0 | ||
|
|
586e53bb42 | ||
|
|
073893ae48 | ||
|
|
a89878a24d | ||
|
|
857ca4eecd | ||
|
|
91d9438421 | ||
|
|
7e5ddcd36b | ||
|
|
6a9a5dbe27 | ||
|
|
63076758a3 | ||
|
|
3019609946 | ||
|
|
64e7057d50 | ||
|
|
54c28fc87f | ||
|
|
77ac333e11 | ||
|
|
6a84ba2523 | ||
|
|
d5ce234d4d | ||
|
|
4bde3ed4b0 | ||
|
|
28d18dd6a5 | ||
|
|
bd068312d9 | ||
|
|
3f19d66c78 | ||
|
|
67e6e38825 | ||
|
|
d37540f032 | ||
|
|
4274b558b6 | ||
|
|
960335c330 | ||
|
|
26bbdead7d | ||
|
|
c130f8e881 | ||
|
|
ea36c6e5d7 | ||
|
|
8f97a332f6 | ||
|
|
4b965a0ff6 | ||
|
|
913c81a0d3 | ||
|
|
6e9a5a010f | ||
|
|
bad21f0ab5 | ||
|
|
b92c819ea2 | ||
|
|
51002066e9 | ||
|
|
b8544e3708 | ||
|
|
fa0e8de0a9 | ||
|
|
1d71a14d2c | ||
|
|
3dca515441 | ||
|
|
c006ed7b10 | ||
|
|
ed358590ce | ||
|
|
8434da60ef | ||
|
|
688394abce | ||
|
|
e199143412 | ||
|
|
8fdec305c4 | ||
|
|
70a628f2c8 | ||
|
|
d917b2e1c9 | ||
|
|
1995781a9f | ||
|
|
338968a493 | ||
|
|
ae43ec0cc9 | ||
|
|
a6db9688cd | ||
|
|
33f9bb50a3 | ||
|
|
a1aefb0cb2 | ||
|
|
17f39e5e39 | ||
|
|
0ed0cc56e9 | ||
|
|
8104caea50 | ||
|
|
1917999f6d | ||
|
|
9be5e7671c | ||
|
|
d6c7b2b1ac | ||
|
|
59d5adace3 | ||
|
|
0e11760f08 | ||
|
|
d937bc692b | ||
|
|
aba135bc8b | ||
|
|
52f83eb682 | ||
|
|
db4a1b0265 | ||
|
|
7c27440916 | ||
|
|
be8e452285 | ||
|
|
504223612d | ||
|
|
df6383d2d8 | ||
|
|
ec6ee82b81 | ||
|
|
860ce558c2 | ||
|
|
801c61549c | ||
|
|
5e06f62ff6 | ||
|
|
52dcd8e749 | ||
|
|
e48e826536 | ||
|
|
1f3c4b66a0 | ||
|
|
87dd1b6310 | ||
|
|
f288573db0 | ||
|
|
284c501532 | ||
|
|
b2f81db4a9 | ||
|
|
fad375c11c | ||
|
|
6c676782aa | ||
|
|
3ff25fb5c1 | ||
|
|
9f40e45b20 | ||
|
|
4d9f3aae97 | ||
|
|
5a31a6c1e2 | ||
|
|
62f598110e | ||
|
|
5749d871b0 | ||
|
|
8121400cf2 | ||
|
|
2b59509fdd | ||
|
|
e2a6edd78f | ||
|
|
4d6682e211 | ||
|
|
ea127cdfa9 | ||
|
|
86f7a87d45 | ||
|
|
8d362ef4de | ||
|
|
b35cdca9bb | ||
|
|
509a7e4628 | ||
|
|
a96b5d1bc4 | ||
|
|
fe25118d04 | ||
|
|
51747d3d36 | ||
|
|
1642276678 | ||
|
|
3f9b8f03af | ||
|
|
d156c8c99e | ||
|
|
87591369b8 | ||
|
|
0a7833ec3d | ||
|
|
206013f2db | ||
|
|
aa14a6a82e | ||
|
|
58b69c2779 | ||
|
|
f562886a7e | ||
|
|
74a2211a6a | ||
|
|
ec0e766c94 | ||
|
|
5b82b94c20 | ||
|
|
edcc1f6e80 | ||
|
|
685b2a8d6d | ||
|
|
2512425868 | ||
|
|
3aa5e8bcd6 | ||
|
|
8d2af7e77f | ||
|
|
6db02ea122 | ||
|
|
ca91b7c43d | ||
|
|
8688fd5b95 | ||
|
|
56a9e8d74b | ||
|
|
53e204db3a | ||
|
|
0a92499dd7 | ||
|
|
cbd26e69d1 | ||
|
|
cce1fa0c90 | ||
|
|
cafb1c1c05 | ||
|
|
0322a1a6a7 | ||
|
|
22a15f5ed6 | ||
|
|
9e12b61849 | ||
|
|
bd2609bcba | ||
|
|
c04a7af22f | ||
|
|
9e3470436a | ||
|
|
d027d99597 | ||
|
|
44da25dd64 | ||
|
|
891366c51d | ||
|
|
1e82d5012b | ||
|
|
f9a1f1a1b7 | ||
|
|
b7bfc253eb | ||
|
|
5569ba92a2 | ||
|
|
1f9d0b5810 | ||
|
|
641186d89c | ||
|
|
e27c668c40 | ||
|
|
4331686818 | ||
|
|
c4018d0648 | ||
|
|
3bfc0c83d8 | ||
|
|
f00c135b69 | ||
|
|
007c38652f | ||
|
|
997c103fba | ||
|
|
6072ffd848 | ||
|
|
de681705e6 | ||
|
|
67af3a5b4e | ||
|
|
e49dc08759 | ||
|
|
433639c471 | ||
|
|
2bfdc482a6 | ||
|
|
1de6ac702d | ||
|
|
15988f0fae | ||
|
|
aea9176f86 | ||
|
|
b0533e6836 | ||
|
|
beb228fa78 | ||
|
|
1bee23cf4f | ||
|
|
42fcf557b8 | ||
|
|
95fef86ec0 | ||
|
|
c70b545ba1 | ||
|
|
a9c633a540 | ||
|
|
552dca9494 | ||
|
|
0308b18400 | ||
|
|
4007f4d452 | ||
|
|
5bc19af196 | ||
|
|
969fea7494 | ||
|
|
10de970814 | ||
|
|
9f2c4bccdf | ||
|
|
a5a57c4076 | ||
|
|
11e41bb4dc | ||
|
|
51f1cdb076 | ||
|
|
09e39ad890 | ||
|
|
018dd91ca1 | ||
|
|
082f9819e9 | ||
|
|
776edd4dd8 | ||
|
|
6380bf7885 | ||
|
|
02af868274 | ||
|
|
bd74ab9718 | ||
|
|
45db7f1d48 | ||
|
|
9998f9b578 | ||
|
|
92f56445fe | ||
|
|
1e0449791d | ||
|
|
653b7d0ac4 | ||
|
|
abb662b606 | ||
|
|
4ca4d4f45e | ||
|
|
e2e062e128 | ||
|
|
e295516928 | ||
|
|
8ab23f66b5 | ||
|
|
9527894b25 | ||
|
|
0927ffca29 | ||
|
|
3db1cad18b | ||
|
|
9f4aafd6b6 | ||
|
|
43fc937469 | ||
|
|
e03bb7432e | ||
|
|
41cf0aaac6 | ||
|
|
735fc6e1bb | ||
|
|
ada369bf08 | ||
|
|
af32f33141 | ||
|
|
70cd166da5 | ||
|
|
70830e0b74 | ||
|
|
e35f2cc938 | ||
|
|
c9964e69c2 | ||
|
|
b60c67ff88 | ||
|
|
241a217f58 | ||
|
|
1879eb36d8 | ||
|
|
0a2ededfcf | ||
|
|
78a1350f15 | ||
|
|
a9c94236c2 | ||
|
|
eab8167a56 | ||
|
|
407d4bce6e | ||
|
|
5cf85368ea | ||
|
|
648cdbaa29 | ||
|
|
6f378ef3ef | ||
|
|
c65687e9f6 | ||
|
|
051e608835 | ||
|
|
eed1648363 | ||
|
|
29b0e86225 | ||
|
|
d16e49fc5f | ||
|
|
db69f6a6f5 | ||
|
|
5c95cbd1d3 | ||
|
|
d3727dde97 | ||
|
|
e8505d79e7 | ||
|
|
0454b65a94 | ||
|
|
1d74a8f757 | ||
|
|
d77e924014 | ||
|
|
d7a0914d13 | ||
|
|
715ff95cf1 | ||
|
|
5d50c80604 | ||
|
|
8e4187fb60 | ||
|
|
a680539b7c | ||
|
|
69a708fd1b | ||
|
|
e0dcdcea28 | ||
|
|
1f81c97371 | ||
|
|
2d71e98b52 | ||
|
|
c71b2dee99 | ||
|
|
26fdfcd25c | ||
|
|
fe8e490ac0 | ||
|
|
106916e7bf | ||
|
|
3c9bf7456e | ||
|
|
a812b52fee | ||
|
|
c91c2a6e3f | ||
|
|
8e025b0823 | ||
|
|
ab906da53d | ||
|
|
f2edb0a033 | ||
|
|
e8b86ca6a1 | ||
|
|
17fd1aea29 | ||
|
|
0c0510599d | ||
|
|
9786db308a | ||
|
|
979c227d54 | ||
|
|
595532e0a5 | ||
|
|
42cedf5b10 | ||
|
|
f4b9635fee | ||
|
|
560c4b3821 | ||
|
|
5da82d8423 | ||
|
|
33425e04c0 | ||
|
|
7535abc298 | ||
|
|
308b321ead | ||
|
|
8976ebfc41 | ||
|
|
4620aa8aa8 | ||
|
|
c96efa76b9 | ||
|
|
40392fff9c | ||
|
|
815a06adad | ||
|
|
22b585057d | ||
|
|
165b129385 | ||
|
|
1946c68ef8 | ||
|
|
d2632bff4f | ||
|
|
d4b7b6baf0 | ||
|
|
11236c67cb | ||
|
|
0b114abb95 | ||
|
|
8000ff733e | ||
|
|
8b5caeb394 | ||
|
|
02b648e36d | ||
|
|
674703f4dc | ||
|
|
64bcbd708a | ||
|
|
2236dcdbed | ||
|
|
af544a95d1 | ||
|
|
22250b4234 | ||
|
|
a27122802d | ||
|
|
ad1ef783ce | ||
|
|
4ae39f56fd | ||
|
|
652d2e6bac | ||
|
|
50031c4836 | ||
|
|
ef363c57ac | ||
|
|
ded2174578 | ||
|
|
c5add52e61 | ||
|
|
1ad55139b4 | ||
|
|
db1874fdac | ||
|
|
23a542e639 | ||
|
|
a8c318f90f | ||
|
|
a3ef7c9234 | ||
|
|
649fb0bebe | ||
|
|
94851da7f9 | ||
|
|
fcf4c011cb | ||
|
|
8f8f42edd5 | ||
|
|
f7479e0cf5 | ||
|
|
ca56ba6327 | ||
|
|
158afa7a27 | ||
|
|
b020cb2f98 | ||
|
|
1c0f6a7913 | ||
|
|
aeb22bf35d | ||
|
|
befcfd10b7 | ||
|
|
ae41a19fb2 | ||
|
|
4c41b1699d | ||
|
|
ff7a72eca8 | ||
|
|
28fe0e31b1 | ||
|
|
be931445ac | ||
|
|
4c10ad471b | ||
|
|
9233422b1a | ||
|
|
b7c7695707 | ||
|
|
7dcf1662b0 | ||
|
|
34ebf1e6e0 | ||
|
|
0a493d1f34 | ||
|
|
e33543aacb | ||
|
|
078bba2fb9 | ||
|
|
38e15da5d0 | ||
|
|
d154611023 | ||
|
|
fa5bfaf15d | ||
|
|
eff8f09dda | ||
|
|
43376996a1 | ||
|
|
93e6daec6b | ||
|
|
2fd15b7d7f | ||
|
|
7eb694822d | ||
|
|
0b683b6994 | ||
|
|
60f871c29c | ||
|
|
07da4831b1 | ||
|
|
dbc0e94c91 | ||
|
|
b987d22419 | ||
|
|
e2dfb9fc4f | ||
|
|
d0de9b4af2 | ||
|
|
7a40497a9f | ||
|
|
d1aaa7c125 | ||
|
|
7bdd973ddc | ||
|
|
a38297f8d0 | ||
|
|
f3067ccfee | ||
|
|
668bc95f15 |
25
.github/ISSUE_TEMPLATE/bug_report.md
vendored
25
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,14 +1,29 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Omega is not working like it should? Let us know!
|
||||
about: Upsilon is not working like it should? Let us know!
|
||||
title: ''
|
||||
labels: Bug, Triage
|
||||
labels: 'Status: Triage, Type: Bug'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
#### Describe the bug
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
#### Environment
|
||||
- Omega Version: {go to settings > about > Omega Version and type the version here}
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Device (please complete the following information):**
|
||||
- The device on which you're running Upsilon (computer, n0110, n0100, etc...)
|
||||
- Upsilon Version: [go to settings > about > Upsilon Version and type the version here]
|
||||
- Upsilon commit: [settings > about > click one time on epsilon version]
|
||||
|
||||
1
.github/ISSUE_TEMPLATE/config.yml
vendored
1
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
13
.github/ISSUE_TEMPLATE/feature_request.md
vendored
13
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,10 +1,17 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for an improvement of Omega
|
||||
about: Suggest an idea for Upsilon
|
||||
title: ''
|
||||
labels: Feature, Triage
|
||||
labels: 'Status: Triage, Type: Feature'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
#### What I want to see in the next version of Omega
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
4
.github/ISSUE_TEMPLATE/other.md
vendored
4
.github/ISSUE_TEMPLATE/other.md
vendored
@@ -1,8 +1,8 @@
|
||||
---
|
||||
name: Other
|
||||
about: A question? A problem? ...
|
||||
about: A question? A problem? …
|
||||
title: ''
|
||||
labels: Triage
|
||||
labels: 'Status: Triage'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
---
|
||||
name: Problems during installation
|
||||
about: Need help to install Omega?
|
||||
about: Need help to install Upsilon?
|
||||
title: ''
|
||||
labels: Installation issue, Triage
|
||||
labels: 'Status: Triage, Type: Installation issue'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
#### Describe the problem
|
||||
**Describe the problem**
|
||||
|
||||
|
||||
#### Logs
|
||||
**Logs**
|
||||
```
|
||||
Copy/paste the logs here (If you have some)
|
||||
```
|
||||
|
||||
#### Environment
|
||||
- Omega Version: {go to settings > about > Omega Version and type the version here}
|
||||
**Environment**
|
||||
- Upsilon Version: {go to settings > about > Upsilon Version and type the version here}
|
||||
|
||||
12
.github/workflows/ci-docker.yml
vendored
12
.github/workflows/ci-docker.yml
vendored
@@ -1,12 +0,0 @@
|
||||
name: Docker Image CI
|
||||
on: [pull_request, push]
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Build the Docker image
|
||||
run: docker build . --file docker/Dockerfile --tag omega:$(date +%s)
|
||||
589
.github/workflows/ci-workflow.yml
vendored
589
.github/workflows/ci-workflow.yml
vendored
@@ -1,123 +1,582 @@
|
||||
name: Continuous integration
|
||||
on: [pull_request, push]
|
||||
|
||||
#on: [pull_request, push]
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
triggerIos:
|
||||
description: 'Run iOS tests'
|
||||
required: true
|
||||
default: 'yes'
|
||||
triggerMacos:
|
||||
description: 'Run macOS tests'
|
||||
required: true
|
||||
default: 'yes'
|
||||
trigger3DS:
|
||||
description: 'Run 3DS tests'
|
||||
required: true
|
||||
default: 'yes'
|
||||
triggerFxcg:
|
||||
description: 'Run fxcg tests'
|
||||
required: true
|
||||
default: 'no'
|
||||
jobs:
|
||||
# nintendo_3ds:
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - run: wget https://github.com/devkitPro/pacman/releases/download/v1.0.2/devkitpro-pacman.amd64.deb -O /tmp/devkitpro-pacman.deb
|
||||
# - run: yes | sudo dpkg -i /tmp/devkitpro-pacman.deb
|
||||
# - run: yes | sudo dkp-pacman -Syu --needed devkitARM 3dstools libctru
|
||||
# - run: echo ::set-env name=DEVKITPRO::/opt/devkitpro
|
||||
# - run: echo ::set-env name=DEVKITARM::/opt/devkitpro/devkitARM
|
||||
# - run: echo ::set-env name=PATH::$DEVKITPRO/tools/bin:$DEVKITARM/bin:$PATH
|
||||
|
||||
# - uses: actions/checkout@v1
|
||||
# with:
|
||||
# submodules: true
|
||||
# - run: make -j2 PLATFORM=simulator TARGET=3ds
|
||||
# - uses: actions/upload-artifact@master
|
||||
# with:
|
||||
# name: epsilon-3ds.3dsx
|
||||
# path: output/release/simulator/3ds/epsilon.3dsx
|
||||
fxcg: # fxcg build is broken for now, disabling it for now to avoid noise
|
||||
if: github.event.inputs.triggerFxcg == 'yes'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential cmake libfreetype-dev -y
|
||||
- name: Get latest gint commit hash
|
||||
run: |
|
||||
LATEST_COMMIT_HASH=$(curl --silent https://git.planet-casio.com/api/v1/repos/Lephenixnoir/gint/branches/master | jq -r .commit.id)
|
||||
echo "Latest commit hash is: $LATEST_COMMIT_HASH"
|
||||
echo "LATEST_COMMIT_HASH=$LATEST_COMMIT_HASH" >> $GITHUB_OUTPUT
|
||||
id: get-latest-commit-hash
|
||||
- name: Cache gint/fxsdk installation
|
||||
id: cache-gint
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.local/*/*
|
||||
!~/.local/share/containers
|
||||
key: ${{ runner.os }}-gint-${{ steps.get-latest-commit-hash.outputs.LATEST_COMMIT_HASH }}
|
||||
- name: Install gint/fxsdk
|
||||
if: steps.cache-gint.outputs.cache-hit != 'true'
|
||||
env:
|
||||
URL: "https://git.planet-casio.com/Lephenixnoir/GiteaPC/archive/master.tar.gz"
|
||||
run: |
|
||||
export PATH="~/.local/bin:$PATH"
|
||||
cd "$(mktemp -d)"
|
||||
curl "$URL" -o giteapc-master.tar.gz
|
||||
tar -xzf giteapc-master.tar.gz
|
||||
cd giteapc
|
||||
python3 giteapc.py install Lephenixnoir/GiteaPC -y
|
||||
sudo apt-get install python3-pil libusb-1.0-0-dev libudev-dev libsdl2-dev libpng-dev libudisks2-dev libglib2.0-dev libmpfr-dev libmpc-dev libppl-dev -y
|
||||
giteapc install Lephenixnoir/fxsdk:noudisks2 Lephenixnoir/sh-elf-binutils Lephenixnoir/sh-elf-gcc -y
|
||||
giteapc install Lephenixnoir/OpenLibm Vhex-Kernel-Core/fxlibc Lephenixnoir/sh-elf-gcc -y
|
||||
giteapc install Lephenixnoir/gint -y
|
||||
- name: Add fxsdk to PATH
|
||||
run: echo "~/.local/bin" >> $GITHUB_PATH
|
||||
- run: make -j2 PLATFORM=simulator TARGET=fxcg
|
||||
- id: 'auth'
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: 'google-github-actions/auth@v0'
|
||||
with:
|
||||
credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
|
||||
- id: 'upload-directory'
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: 'google-github-actions/upload-cloud-storage@v0'
|
||||
with:
|
||||
path: 'output/release/simulator/fxcg/epsilon.g3a'
|
||||
destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
|
||||
parent: false
|
||||
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: Yaya-Cout/Upsilon-binfiles
|
||||
ref: 'main'
|
||||
token: ${{ secrets.PAT_UPSILON_BINFILES }}
|
||||
path: 'binfiles'
|
||||
# TODO: Handle git conflicts using rebase
|
||||
- name: Upload binary files to website
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
|
||||
run: |
|
||||
cp -r output/release/simulator/fxcg/epsilon.g3a binfiles/binaries/dev/simulator
|
||||
cd binfiles
|
||||
git add -A
|
||||
git config --global user.email "ci@github.com"
|
||||
git config --global user.name "GitHub Upsilon CI"
|
||||
git pull
|
||||
git commit -m "Update from CI"
|
||||
git push
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: epsilon.g3a
|
||||
path: output/release/simulator/fxcg/epsilon.g3a
|
||||
nintendo_3ds:
|
||||
if: github.event.inputs.trigger3DS == 'yes' || github.event.inputs.trigger3DS == ''
|
||||
runs-on: ubuntu-latest
|
||||
container: devkitpro/devkitarm:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
- run: sudo apt-get update
|
||||
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config -y
|
||||
- run: yes | sudo dkp-pacman -S --needed devkitARM 3dstools libctru
|
||||
- run: wget https://github.com/3DSGuy/Project_CTR/releases/download/makerom-v0.18.3/makerom-v0.18.3-ubuntu_x86_64.zip
|
||||
- run: unzip makerom-v0.18.3-ubuntu_x86_64.zip
|
||||
- run: rm makerom-v0.18.3-ubuntu_x86_64.zip
|
||||
- run: chmod +x ./makerom
|
||||
- run: echo "PATH=.:$PATH" >> $GITHUB_ENV
|
||||
- run: make -j2 PLATFORM=simulator TARGET=3ds
|
||||
- run: make -j2 PLATFORM=simulator TARGET=3ds epsilon.cia
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: epsilon-3ds.3dsx
|
||||
path: output/release/simulator/3ds/epsilon.3dsx
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: epsilon-3ds.cia
|
||||
path: output/release/simulator/3ds/epsilon.cia
|
||||
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: Yaya-Cout/Upsilon-binfiles
|
||||
ref: 'main'
|
||||
token: ${{ secrets.PAT_UPSILON_BINFILES }}
|
||||
path: 'binfiles'
|
||||
# TODO: Handle git conflicts using rebase
|
||||
- name: Upload binary files to website
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
|
||||
run: |
|
||||
cp -r output/release/simulator/3ds/epsilon.3dsx output/release/simulator/3ds/epsilon.cia binfiles/binaries/dev/simulator
|
||||
cd binfiles
|
||||
git add -A
|
||||
git config --global user.email "ci@github.com"
|
||||
git config --global user.name "GitHub Upsilon CI"
|
||||
git pull
|
||||
git commit -m "Update from CI"
|
||||
git push
|
||||
android:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
- run: make -j2 PLATFORM=simulator TARGET=android
|
||||
- uses: actions/upload-artifact@master
|
||||
submodules: 'recursive'
|
||||
- run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install imagemagick libfreetype-dev libpng-dev
|
||||
- name: Set up JDK 25
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: '25'
|
||||
distribution: 'temurin'
|
||||
- run: wget -nv https://dl.google.com/android/repository/android-ndk-r21e-linux-x86_64.zip
|
||||
- run: unzip -q android-ndk-r21e-linux-x86_64.zip
|
||||
- run: make -j2 PLATFORM=simulator TARGET=android NDK_PATH=./android-ndk-r21e
|
||||
- id: 'auth'
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: 'google-github-actions/auth@v0'
|
||||
with:
|
||||
credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
|
||||
- id: 'upload-file'
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: 'google-github-actions/upload-cloud-storage@v0'
|
||||
with:
|
||||
path: 'output/release/simulator/android/epsilon.apk'
|
||||
destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
|
||||
parent: false
|
||||
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: Yaya-Cout/Upsilon-binfiles
|
||||
ref: 'main'
|
||||
token: ${{ secrets.PAT_UPSILON_BINFILES }}
|
||||
path: 'binfiles'
|
||||
# TODO: Handle git conflicts using rebase
|
||||
- name: Upload binary files to website
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
|
||||
run: |
|
||||
cp -r output/release/simulator/android/epsilon.apk binfiles/binaries/dev/simulator
|
||||
cd binfiles
|
||||
git add -A
|
||||
git config --global user.email "ci@github.com"
|
||||
git config --global user.name "GitHub Upsilon CI"
|
||||
git pull
|
||||
git commit -m "Update from CI"
|
||||
git push
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: epsilon-android.apk
|
||||
path: output/release/simulator/android/epsilon.apk
|
||||
n0100:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04-arm
|
||||
steps:
|
||||
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
|
||||
- uses: numworks/setup-arm-toolchain@v1
|
||||
- uses: actions/checkout@v1
|
||||
- run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
submodules: 'recursive'
|
||||
- run: mkdir final-output
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=en output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.en.bin
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=en output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.en.internal.bin
|
||||
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
|
||||
# We need to duplicate make to work around i18n generator race condition in Makefile leading to inconsistent incremental rebuilds
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=fr output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.fr.bin
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=fr output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.fr.internal.bin
|
||||
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=nl output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.nl.bin
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=nl output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.nl.internal.bin
|
||||
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=pt output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.pt.bin
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=pt output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.pt.internal.bin
|
||||
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=it output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.it.bin
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=it output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.it.internal.bin
|
||||
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=de output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.de.bin
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=de output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.de.internal.bin
|
||||
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=es output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.es.bin
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=es output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.es.internal.bin
|
||||
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=hu output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.hu.bin
|
||||
- run: make -j2 MODEL=n0100 EPSILON_I18N=hu output/release/device/n0100/epsilon.onboarding.two_binaries
|
||||
- run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.hu.internal.bin
|
||||
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
|
||||
- run: make -j2 MODEL=n0100 output/release/device/n0100/flasher.light.bin
|
||||
- run: mv output/release/device/n0100/flasher.light.bin final-output/flasher.light.bin
|
||||
- run: make -j2 MODEL=n0100 output/release/device/n0100/flasher.verbose.bin
|
||||
- run: mv output/release/device/n0100/flasher.verbose.bin final-output/flasher.verbose.bin
|
||||
- run: find final-output/ -type f -exec bash -c "shasum -a 256 -b {} > {}.sha256" \;
|
||||
- run: tar cvfz binpack-n0100.tgz final-output/*
|
||||
- uses: actions/upload-artifact@master
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: epsilon-binpack-n0100.tgz
|
||||
path: binpack-n0100.tgz
|
||||
n0110:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
|
||||
- uses: numworks/setup-arm-toolchain@v1
|
||||
- uses: actions/checkout@v1
|
||||
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
- run: make -j2 epsilon.dfu
|
||||
- run: make -j2 epsilon.onboarding.dfu
|
||||
- run: make -j2 epsilon.onboarding.update.dfu
|
||||
- run: make -j2 epsilon.onboarding.beta.dfu
|
||||
- run: make -j2 flasher.light.dfu
|
||||
- run: make -j2 flasher.verbose.dfu
|
||||
- run: make -j2 bench.ram.dfu
|
||||
- run: make -j2 bench.flash.dfu
|
||||
- run: make -j2 binpack
|
||||
repository: Yaya-Cout/Upsilon-binfiles
|
||||
ref: 'main'
|
||||
token: ${{ secrets.PAT_UPSILON_BINFILES }}
|
||||
path: 'binfiles'
|
||||
# TODO: Handle git conflicts using rebase
|
||||
- name: Upload binary files to website
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
|
||||
run: |
|
||||
cp -r final-output/* binfiles/binaries/dev/n100
|
||||
cd binfiles
|
||||
git add -A
|
||||
git config --global user.email "ci@github.com"
|
||||
git config --global user.name "GitHub Upsilon CI"
|
||||
git pull
|
||||
git commit -m "Update from CI"
|
||||
git push
|
||||
n0110:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
steps:
|
||||
- run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- run: make -j2 MODEL=n0110 epsilon.dfu
|
||||
- run: make -j2 MODEL=n0110 epsilon.onboarding.dfu
|
||||
- run: make -j2 MODEL=n0110 epsilon.onboarding.update.dfu
|
||||
- run: make -j2 MODEL=n0110 epsilon.onboarding.beta.dfu
|
||||
- run: make -j2 MODEL=n0110 flasher.light.dfu
|
||||
- run: make -j2 MODEL=n0110 flasher.verbose.dfu
|
||||
- run: make -j2 MODEL=n0110 flasher.verbose.bin
|
||||
- run: make -j2 MODEL=n0110 bench.ram.dfu
|
||||
# - run: make -j2 MODEL=n0110 bench.flash.dfu
|
||||
- run: make -j2 MODEL=n0110 binpack
|
||||
- run: cp output/release/device/n0110/binpack-n0110-`git rev-parse HEAD | head -c 7`.tgz output/release/device/n0110/binpack-n0110.tgz
|
||||
- uses: actions/upload-artifact@master
|
||||
- run: cp output/release/device/n0110/flasher.verbose.bin output/release/device/n0110/binpack/
|
||||
- run: cd output/release/device/n0110 && for binary in *.bin; do shasum -a 256 -b binpack/${binary} > binpack/${binary}.sha256;done
|
||||
- run: cp output/release/device/n0110/binpack-n0110-`git rev-parse HEAD | head -c 7`.tgz output/release/device/n0110/binpack/binpack.tgz
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: epsilon-binpack-n0110.tgz
|
||||
path: output/release/device/n0110/binpack-n0110.tgz
|
||||
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: Yaya-Cout/Upsilon-binfiles
|
||||
ref: 'main'
|
||||
token: ${{ secrets.PAT_UPSILON_BINFILES }}
|
||||
path: 'binfiles'
|
||||
# TODO: Handle git conflicts using rebase
|
||||
- name: Upload binary files to website
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
|
||||
run: |
|
||||
cp -r output/release/device/n0110/binpack/* binfiles/binaries/dev/n110
|
||||
cd binfiles
|
||||
git add -A
|
||||
git config --global user.email "ci@github.com"
|
||||
git config --global user.name "GitHub Upsilon CI"
|
||||
git pull
|
||||
git commit -m "Update from CI"
|
||||
git push
|
||||
bootloader:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
steps:
|
||||
- run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- run: make -j2 MODEL=n0110 bootloader
|
||||
- run: make -j2 epsilon.A.dfu epsilon.B.dfu
|
||||
- run: make -j2 epsilon.onboarding.A.dfu
|
||||
- run: make -j2 epsilon.onboarding.B.dfu
|
||||
- run: make -j2 epsilon.onboarding.update.A.dfu
|
||||
- run: make -j2 epsilon.onboarding.update.B.dfu
|
||||
- run: make -j2 epsilon.onboarding.beta.A.dfu
|
||||
- run: make -j2 epsilon.onboarding.beta.B.dfu
|
||||
- run: make -j2 binpack
|
||||
- run: cp output/release/device/bootloader/binpack-bootloader-`git rev-parse HEAD | head -c 7`.tgz output/release/device/bootloader/binpack-bootloader.tgz
|
||||
- run: cp output/release/device/n0110/bootloader.bin output/release/device/bootloader/binpack/
|
||||
- run: cp output/release/device/n0110/bootloader.bin output/release/device/bootloader/
|
||||
- run: cd output/release/device/bootloader && for binary in *.bin; do shasum -a 256 -b binpack/${binary} > binpack/${binary}.sha256;done
|
||||
- run: cd output/release/device/bootloader && tar cvfz binpack-bootloader.tgz binpack/*
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: epsilon-binpack-bootloader.tgz
|
||||
path: output/release/device/bootloader/binpack-bootloader.tgz
|
||||
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: Yaya-Cout/Upsilon-binfiles
|
||||
ref: 'main'
|
||||
token: ${{ secrets.PAT_UPSILON_BINFILES }}
|
||||
path: 'binfiles'
|
||||
# TODO: Handle git conflicts using rebase
|
||||
- name: Upload binary files to website
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
|
||||
run: |
|
||||
cp -r output/release/device/bootloader/binpack/* binfiles/binaries/dev/n110
|
||||
cd binfiles
|
||||
git add -A
|
||||
git config --global user.email "ci@github.com"
|
||||
git config --global user.name "GitHub Upsilon CI"
|
||||
git pull
|
||||
git commit -m "Update from CI"
|
||||
git push
|
||||
windows:
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: msys2/setup-msys2@v2
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- run: pacman -S --noconfirm mingw-w64-x86_64-gcc mingw-w64-x86_64-freetype mingw-w64-x86_64-pkg-config make mingw-w64-x86_64-python3 mingw-w64-x86_64-libjpeg-turbo mingw-w64-x86_64-libpng git
|
||||
- run: make -j2 PLATFORM=simulator
|
||||
- run: make -j2 PLATFORM=simulator test.exe
|
||||
- run: cmd /c output\release\simulator\windows\test.exe --headless
|
||||
- id: 'auth'
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: 'google-github-actions/auth@v0'
|
||||
with:
|
||||
credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
|
||||
- id: 'upload-file'
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: 'google-github-actions/upload-cloud-storage@v0'
|
||||
with:
|
||||
path: 'output/release/simulator/windows/epsilon.exe'
|
||||
destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
|
||||
parent: false
|
||||
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: Yaya-Cout/Upsilon-binfiles
|
||||
ref: 'main'
|
||||
token: ${{ secrets.PAT_UPSILON_BINFILES }}
|
||||
path: 'binfiles'
|
||||
# TODO: Handle git conflicts using rebase
|
||||
- name: Upload binary files to website
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
|
||||
run: |
|
||||
cp -r output/release/simulator/windows/epsilon.exe binfiles/binaries/dev/simulator
|
||||
cd binfiles
|
||||
git add -A
|
||||
git config --global user.email "ci@github.com"
|
||||
git config --global user.name "GitHub Upsilon CI"
|
||||
git pull
|
||||
git commit -m "Update from CI"
|
||||
git push
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: epsilon-windows.exe
|
||||
path: output/release/simulator/windows/epsilon.exe
|
||||
web:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: numworks/setup-emscripten@v2
|
||||
- uses: numworks/setup-emscripten@master
|
||||
with:
|
||||
sdk: latest-upstream
|
||||
- uses: actions/checkout@v1
|
||||
sdk: latest
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
submodules: 'recursive'
|
||||
# Install the Linux toolchin to avoid dependancies issues, but maybe only libpng is needed
|
||||
- run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config libxtst-dev
|
||||
- run: make -j2 PLATFORM=simulator TARGET=web
|
||||
- uses: actions/upload-artifact@master
|
||||
- run: make -j2 PLATFORM=simulator TARGET=web test.js
|
||||
- run: node output/release/simulator/web/test.js --headless
|
||||
- id: 'auth'
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: 'google-github-actions/auth@v0'
|
||||
with:
|
||||
credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
|
||||
- id: 'upload-file'
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: 'google-github-actions/upload-cloud-storage@v0'
|
||||
with:
|
||||
path: 'output/release/simulator/web/epsilon.js'
|
||||
destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
|
||||
parent: false
|
||||
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: Yaya-Cout/Upsilon-binfiles
|
||||
ref: 'main'
|
||||
token: ${{ secrets.PAT_UPSILON_BINFILES }}
|
||||
path: 'binfiles'
|
||||
# TODO: Handle git conflicts using rebase
|
||||
- name: Upload binary files to website
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
|
||||
run: |
|
||||
cp -r output/release/simulator/web/epsilon.zip binfiles/binaries/dev/simulator
|
||||
cd binfiles
|
||||
git add -A
|
||||
git config --global user.email "ci@github.com"
|
||||
git config --global user.name "GitHub Upsilon CI"
|
||||
git pull
|
||||
git commit -m "Update from CI"
|
||||
git push
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: epsilon-web.zip
|
||||
path: output/release/simulator/web/epsilon.zip
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
|
||||
- uses: actions/checkout@v1
|
||||
- run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config libxtst-dev
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: true
|
||||
submodules: 'recursive'
|
||||
- run: make -j2 PLATFORM=simulator
|
||||
- uses: actions/upload-artifact@master
|
||||
- run: make -j2 PLATFORM=simulator test.bin
|
||||
- run: output/release/simulator/linux/test.bin --headless
|
||||
- id: 'auth'
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: 'google-github-actions/auth@v0'
|
||||
with:
|
||||
credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
|
||||
- id: 'upload-file'
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: 'google-github-actions/upload-cloud-storage@v0'
|
||||
with:
|
||||
path: 'output/release/simulator/linux/epsilon.bin'
|
||||
destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
|
||||
parent: false
|
||||
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: Yaya-Cout/Upsilon-binfiles
|
||||
ref: 'main'
|
||||
token: ${{ secrets.PAT_UPSILON_BINFILES }}
|
||||
path: 'binfiles'
|
||||
# TODO: Handle git conflicts using rebase
|
||||
- name: Upload binary files to website
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
|
||||
run: |
|
||||
cp -r output/release/simulator/linux/epsilon.bin binfiles/binaries/dev/simulator
|
||||
cd binfiles
|
||||
git add -A
|
||||
git config --global user.email "ci@github.com"
|
||||
git config --global user.name "GitHub Upsilon CI"
|
||||
git pull
|
||||
git commit -m "Update from CI"
|
||||
git push
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: epsilon-linux.bin
|
||||
path: output/release/simulator/linux/epsilon.bin
|
||||
- run: make -j2 PLATFORM=simulator test.headless.bin
|
||||
macos:
|
||||
if: github.event.inputs.triggerMacos == 'yes' || github.event.inputs.triggerMacos == ''
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- run: brew install python-setuptools
|
||||
- run: brew install numworks/tap/epsilon-sdk
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- run: make -j2 PLATFORM=simulator
|
||||
- run: make -j2 PLATFORM=simulator ARCH=x86_64 test.bin
|
||||
- run: output/release/simulator/macos/x86_64/test.bin --headless
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: epsilon-macos.zip
|
||||
path: output/release/simulator/macos/epsilon.app
|
||||
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: Yaya-Cout/Upsilon-binfiles
|
||||
ref: 'main'
|
||||
token: ${{ secrets.PAT_UPSILON_BINFILES }}
|
||||
path: 'binfiles'
|
||||
# TODO: Handle git conflicts using rebase
|
||||
- name: Upload binary files to website
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
|
||||
run: |
|
||||
cp -r output/release/simulator/macos/epsilon.app binfiles/binaries/dev/simulator
|
||||
cd binfiles
|
||||
git add -A
|
||||
git config --global user.email "ci@github.com"
|
||||
git config --global user.name "GitHub Upsilon CI"
|
||||
git pull
|
||||
git commit -m "Update from CI"
|
||||
git push
|
||||
ios:
|
||||
if: github.event.inputs.triggerIos == 'yes' || github.event.inputs.triggerIos == ''
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- run: brew install python-setuptools
|
||||
- run: brew install numworks/tap/epsilon-sdk
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- run: make -j2 PLATFORM=simulator TARGET=ios EPSILON_TELEMETRY=0
|
||||
- run: make -j2 PLATFORM=simulator TARGET=ios EPSILON_TELEMETRY=0 APPLE_PLATFORM=ios-simulator
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: epsilon-ios.ipa
|
||||
path: output/release/simulator/ios/epsilon.ipa
|
||||
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: Yaya-Cout/Upsilon-binfiles
|
||||
ref: 'main'
|
||||
token: ${{ secrets.PAT_UPSILON_BINFILES }}
|
||||
path: 'binfiles'
|
||||
# TODO: Handle git conflicts using rebase
|
||||
- name: Upload binary files to website
|
||||
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
|
||||
run: |
|
||||
cp -r output/release/simulator/ios/epsilon.ipa binfiles/binaries/dev/simulator
|
||||
cd binfiles
|
||||
git add -A
|
||||
git config --global user.email "ci@github.com"
|
||||
git config --global user.name "GitHub Upsilon CI"
|
||||
git pull
|
||||
git commit -m "Update from CI"
|
||||
git push
|
||||
|
||||
env:
|
||||
ACCEPT_OFFICIAL_TOS: 1
|
||||
|
||||
37
.github/workflows/metric-workflow.yml
vendored
37
.github/workflows/metric-workflow.yml
vendored
@@ -1,38 +1,45 @@
|
||||
name: Metrics
|
||||
on: [pull_request]
|
||||
on: [pull_request_target]
|
||||
|
||||
jobs:
|
||||
binary-size:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04-arm
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
|
||||
- name: Install ARM toolchain
|
||||
uses: numworks/setup-arm-toolchain@v1
|
||||
run: sudo apt-get install gcc-arm-none-eabi binutils-arm-none-eabi
|
||||
- name: Checkout PR base
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{ github.event.pull_request.base.sha }}
|
||||
path: base
|
||||
- name: Build base
|
||||
run: make -j2 -C base epsilon.elf
|
||||
run: make -j2 -C base MODEL=n0110 epsilon.elf
|
||||
- name: Checkout PR head
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
submodules: recursive
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
path: head
|
||||
- name: Build head
|
||||
run: make -j2 -C head epsilon.elf
|
||||
run: make -j2 -C head MODEL=n0110 epsilon.elf
|
||||
- name: Retrieve binary size analysis
|
||||
id: binary_size
|
||||
run: echo "::set-output name=table::$(python3 head/build/metrics/binary_size.py base/output/release/device/n0110/epsilon.elf head/output/release/device/n0110/epsilon.elf --labels Base Head --sections .text .rodata .bss .data --custom 'Total (RAM)' .data .bss --custom 'Total (ROM)' .text .rodata .data --escape)"
|
||||
- name: Prepare comment auth
|
||||
run: echo "::set-env name=GITHUB_TOKEN::$(echo YjgxYTk1YTQ4YzYxNjU4ZTA3YWQzNDYwNTk3ZTI2MTlkODU5MThlOQo= | base64 --decode)"
|
||||
run: |
|
||||
table="$(python3 head/build/metrics/binary_size.py base/output/release/device/n0110/epsilon.elf head/output/release/device/n0110/epsilon.elf --labels Base Head --sections .text .rodata .bss .data --custom 'Total (RAM)' .data .bss --custom 'Total (ROM)' .text .rodata .data --escape)"
|
||||
{
|
||||
echo 'table<<EOF'
|
||||
echo "${table//%0A/$'\n'}"
|
||||
echo EOF
|
||||
} >> "$GITHUB_ENV"
|
||||
- name: Add comment
|
||||
uses: actions/github@v1.0.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }}
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
args: comment ${{ steps.binary_size.outputs.table }}
|
||||
script: |
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.payload.pull_request.number,
|
||||
body: `${{ env.table }}`,
|
||||
});
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -6,3 +6,7 @@ epsilon.map
|
||||
.vscode
|
||||
.DS_Store
|
||||
.gradle
|
||||
.idea/
|
||||
.vs
|
||||
.cache/
|
||||
compile_commands.json
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
image: gcc
|
||||
|
||||
stages:
|
||||
- build
|
||||
|
||||
job:build:
|
||||
stage: build
|
||||
before_script:
|
||||
- "echo 'deb http://httpredir.debian.org/debian jessie main contrib \n deb-src http://httpredir.debian.org/debian jessie main contrib \n deb http://httpredir.debian.org/debian jessie-updates main contrib \n deb-src http://httpredir.debian.org/debian jessie-updates main contrib \n deb http://security.debian.org/ jessie/updates main contrib \n deb-src http://security.debian.org/ jessie/updates main contrib ' > /etc/apt/source.list"
|
||||
- "apt-get update"
|
||||
- "apt -y install build-essential git imagemagick libx11-dev libxext-dev libfreetype6-dev libpng-dev libjpeg-dev pkg-config fltk1.3-dev gcc-arm-none-eabi nodejs npm"
|
||||
- "git submodule update --init --recursive"
|
||||
- "git clone https://github.com/RedGl0w/omega-auto-increment"
|
||||
- "cd omega-auto-increment"
|
||||
- "npm i request exeq"
|
||||
- "PrivateToken=$PrivateToken node index.js"
|
||||
- "cd .."
|
||||
script:
|
||||
- make clean
|
||||
- make MODEL=n0100 epsilon.bin
|
||||
artifacts:
|
||||
paths:
|
||||
- output/release/device/n0100/epsilon.bin
|
||||
- omega-auto-increment/version.txt
|
||||
name: artifact:build:simulator
|
||||
|
||||
11
.gitmodules
vendored
11
.gitmodules
vendored
@@ -1,9 +1,6 @@
|
||||
[submodule "apps/rpn"]
|
||||
path = apps/rpn
|
||||
url = https://github.com/Omega-Numworks/Omega-RPN.git
|
||||
[submodule "apps/atom"]
|
||||
path = apps/atom
|
||||
url = https://github.com/Omega-Numworks/Omega-Atom.git
|
||||
[submodule "themes"]
|
||||
path = themes
|
||||
url = https://github.com/Omega-Numworks/Omega-Themes.git
|
||||
url = https://github.com/UpsilonNumworks/Upsilon-RPN.git
|
||||
[submodule "apps/atomic"]
|
||||
path = apps/atomic
|
||||
url = https://github.com/UpsilonNumworks/atomic
|
||||
|
||||
45
Makefile
45
Makefile
@@ -12,16 +12,40 @@ include build/toolchain.$(TOOLCHAIN).mak
|
||||
include build/variants.mak
|
||||
include build/helpers.mk
|
||||
|
||||
ifeq (${MODEL}, n0110)
|
||||
apps_list = ${EPSILON_APPS}
|
||||
ifeq (${MODEL}, n0100)
|
||||
ifeq ($(filter reader,$(apps_list)),)
|
||||
$(warning reader app included, removing it on n0100. )
|
||||
EPSILON_APPS := $(filter-out reader,$(EPSILON_APPS))
|
||||
endif
|
||||
ifneq ($(words $(EPSILON_I18N)), 1)
|
||||
$(warning Only use 1 language on n0100, defaulting to en. )
|
||||
EPSILON_I18N := en
|
||||
endif
|
||||
ifeq ($(INCLUDE_ULAB), 1)
|
||||
$(warning Removing uLab on n0100. )
|
||||
INCLUDE_ULAB := 0
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(filter reader,$(apps_list)),)
|
||||
HAS_READER := 1
|
||||
endif
|
||||
|
||||
# Remove the external apps for the n0100
|
||||
ifeq (${MODEL}, n0100)
|
||||
apps_list = $(foreach i, ${EPSILON_APPS}, $(if $(filter external, $(i)),,$(i)))
|
||||
else
|
||||
apps_list = $(foreach i, ${EPSILON_APPS}, $(if $(filter external, $(i)),,$(i)))
|
||||
apps_list = ${EPSILON_APPS}
|
||||
endif
|
||||
|
||||
ifdef FORCE_EXTERNAL
|
||||
apps_list = ${EPSILON_APPS}
|
||||
endif
|
||||
|
||||
ifeq ($(INCLUDE_ULAB), 1)
|
||||
SFLAGS += -DINCLUDE_ULAB
|
||||
endif
|
||||
|
||||
ifdef HOME_DISPLAY_EXTERNALS
|
||||
ifneq ($(filter external,$(apps_list)),)
|
||||
SFLAGS += -DHOME_DISPLAY_EXTERNALS
|
||||
@@ -69,6 +93,7 @@ help:
|
||||
@echo " make PLATFORM=simulator TARGET=web"
|
||||
@echo " make PLATFORM=simulator TARGET=windows"
|
||||
@echo " make PLATFORM=simulator TARGET=3ds"
|
||||
@echo " make PLATFORM=simulator TARGET=fxcg"
|
||||
|
||||
.PHONY: doc
|
||||
doc:
|
||||
@@ -82,7 +107,7 @@ print-%:
|
||||
@echo $*\'s origin is $(origin $*)
|
||||
|
||||
# Since we're building out-of-tree, we need to make sure the output directories
|
||||
# are created, otherwise the receipes will fail (e.g. gcc will fail to create
|
||||
# are created, otherwise the recipes will fail (e.g. gcc will fail to create
|
||||
# "output/foo/bar.o" because the directory "output/foo" doesn't exist).
|
||||
# We need to mark those directories as precious, otherwise Make will try to get
|
||||
# rid of them upon completion (and fail, since those folders won't be empty).
|
||||
@@ -103,6 +128,7 @@ ifndef USE_LIBA
|
||||
endif
|
||||
ifeq ($(USE_LIBA),0)
|
||||
include liba/Makefile.bridge
|
||||
include libaxx/Makefile.bridge
|
||||
else
|
||||
SFLAGS += -ffreestanding -nostdinc -nostdlib
|
||||
include liba/Makefile
|
||||
@@ -114,6 +140,7 @@ include poincare/Makefile
|
||||
include python/Makefile
|
||||
include escher/Makefile
|
||||
# Executable Makefiles
|
||||
include bootloader/Makefile
|
||||
include apps/Makefile
|
||||
include build/struct_layout/Makefile
|
||||
include build/scenario/Makefile
|
||||
@@ -186,3 +213,13 @@ clean_run: cleanandcompile
|
||||
.PHONY: run
|
||||
run: compile
|
||||
${MAKE} start
|
||||
|
||||
.PHONY: translations
|
||||
translations:
|
||||
@echo "TRANSLATIONS"
|
||||
$(Q) ${PYTHON} build/utilities/translate.py
|
||||
|
||||
.PHONY: translations_clean
|
||||
translations_clean:
|
||||
@echo "TRANSLATIONS CLEAN"
|
||||
$(Q) ${PYTHON} build/utilities/translations_clean.py
|
||||
|
||||
507
README.fr.md
Normal file
507
README.fr.md
Normal file
@@ -0,0 +1,507 @@
|
||||
<p align="center"><img src="https://github.com/Laporte12974/UpsilonDesign/blob/89a15953ae128aef8aa7d066dcaaf8d5c70f02a5/UPSILogo.png" /></p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="cc by-nc-sa 4.0" src="https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-525252.svg?labelColor=292929&logo=creative%20commons&style=for-the-badge" /></a>
|
||||
<a href="https://github.com/UpsilonNumworks/Upsilon/issues"><img alt="Issues" src="https://img.shields.io/github/issues/Lauryy06/Upsilon.svg?labelColor=292929&logo=git&style=for-the-badge" /></a>
|
||||
<br/>
|
||||
<a href="https://discord.gg/sbGvhWETAd"><img alt="Discord" src="https://img.shields.io/discord/663420259851567114?color=blue&labelColor=292929&label=chat%20-%20discord&logo=discord&style=for-the-badge" /></a>
|
||||
</p>
|
||||
|
||||
> Don't understand French ? Speak English ? here's the [english README](./README.md) !
|
||||
|
||||
## À propos
|
||||
|
||||
Upsilon est un fork d'Omega, un fork d'Epsilon, l'OS de NumWorks tournant sur les calculatrices du même nom, qui apporte beaucoup de fonctionnalités en plus, mais qui fut archivé et fermé pour des raisons légales après un changement de politique de NumWorks. Upsilon est fait pour ceux qui aimeraient voir un futur pour les OS créés par les utilisateurs pour NumWorks, même après l'arrêt du projet initial.
|
||||
|
||||
### Quelques fonctionnalités supplémentaires
|
||||
|
||||
- Un module Python Kandinsky amélioré
|
||||
- Un support pour fonds d'écrans personnalisés
|
||||
- Des applications externes
|
||||
- Un thème Upsilon
|
||||
- La surcharge des opérateurs en Python
|
||||
- Un tableau périodique légèrement amélioré
|
||||
- L'utilisation possible du signe "=" dans les calculs
|
||||
- *Ainsi que tout ce qui a été ajouté sur Omega, et bien plus...* [Changelogs complets d'Omega](https://github.com/Omega-Numworks/Omega/wiki/Changelog) | [Fonctionnalités principales d'Omega & captures d'écran](https://github.com/Omega-Numworks/Omega/wiki/Main-features).
|
||||
|
||||
## Installation
|
||||
|
||||
### Site web
|
||||
|
||||
Rendez-vous sur le [site d'Upsilon](https://getupsilon.web.app/) à la section "Installer".
|
||||
Si votre calculatrice est reconnue, qu'elle contient une version d'Epsilon inférieure à 16 et que votre navigateur accepte WebUSB, la page vous proposera d'installer Upsilon.
|
||||
Ne débranchez votre calculatrice qu'une fois l'installation terminée.
|
||||
|
||||
### Manuelle
|
||||
|
||||
*Vous pouvez vous référer à ce [site internet](https://www.numworks.com/resources/engineering/software/build/) pour la première étape si vous avez des erreurs*
|
||||
|
||||
### 1. Installation du SDK
|
||||
|
||||
<br>
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>1.1 Linux</b></summary>
|
||||
|
||||
<br>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Debian ou Ubuntu</summary>
|
||||
|
||||
<br>
|
||||
|
||||
Il suffit juste d'installer les dépendances en tapant ces commandes dans un terminal en mode super-utilisateur.
|
||||
|
||||
```bash
|
||||
apt-get install build-essential git imagemagick libx11-dev libxext-dev libfreetype6-dev libpng-dev libjpeg-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
|
||||
```
|
||||
|
||||
C'est fait ! Vous pouvez aller à l'étape 2.
|
||||
|
||||
<br>
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Fedora</summary>
|
||||
|
||||
<br>
|
||||
|
||||
Installez toutes les dépendances grâce à cette commande :
|
||||
|
||||
```bash
|
||||
dnf install make automake gcc gcc-c++ kernel-devel git ImageMagick libX11-devel libXext-devel freetype-devel libpng-devel libjpeg-devel pkg-config arm-none-eabi-gcc-cs arm-none-eabi-gcc-cs-c++
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Nix/Nixos</summary>
|
||||
|
||||
<br>
|
||||
|
||||
Installez toutes les dépendances grâce à cette commande :
|
||||
```bash
|
||||
nix-env -p gcc libpng libjpeg xorg.libX11 pkg-config freetype xorg.libXext python3 imagemagick python310Packages.lz4 python310Packages.pypng python310Packages.pypng gcc-arm-embedded
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>1.2 Mac</b></summary>
|
||||
|
||||
<br>
|
||||
|
||||
Il est recommandé d'utiliser [Homebrew](https://brew.sh/). Une fois installé, utilisez :
|
||||
|
||||
```bash
|
||||
brew install numworks/tap/epsilon-sdk
|
||||
```
|
||||
|
||||
Et toutes les dépendances seront installées.
|
||||
|
||||
<br>
|
||||
|
||||
Vous pouvez aller à l'étape 2.
|
||||
|
||||
<br>
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>1.3 Windows</b></summary>
|
||||
|
||||
[Git](http://git-scm.com) doit être installé.
|
||||
|
||||
<br>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Avec Msys2/Mingw (Supportés par NumWorks bien qu'il y ait beaucoup de bugs)</summary>
|
||||
|
||||
L'environnement de compilation [Msys2](https://www.msys2.org/) est recommandé par NumWorks pour obtenir la plupart des outils requis facilement. C'est ici que vous allez copier-coller toutes les commandes de ce tutoriel. Une fois installé, copiez-collez ces deux commandes dans le terminal:
|
||||
|
||||
```bash
|
||||
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-freetype mingw-w64-x86_64-pkg-config mingw-w64-x86_64-libusb git make python
|
||||
echo "export PATH=/mingw64/bin:$PATH" >> .bashrc
|
||||
```
|
||||
|
||||
Ensuite, vous devrez installer [GCC toolchain for ARM](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads). Quand il vous est demandé de choisir un dossier d'installation, choisissez `C:\msys64\home\User\gcc-arm\`. Il vous faudra ensuite ajouter ce dossier à votre $PATH. Tapez juste:
|
||||
|
||||
```bash
|
||||
echo "export PATH=$PATH:$HOME/gcc-arm/bin" >> .bashrc
|
||||
```
|
||||
|
||||
Redémarrez votre terminal et vous pouvez aller à l'étape 2!
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Avec WSL 2</summary>
|
||||
|
||||
WSL est un système qui virtualise un environnement GNU/Linux dans Windows.
|
||||
|
||||
Votre version de Windows doit être >= 1903.
|
||||
|
||||
#### Installation de WSL
|
||||
|
||||
1. Apuyez simultanément sur les touches "Windows" et "X" puis cliquez sur "PowerShell Administrateur". Entrez ensuite ceci dans la nouvelle fenêtre:
|
||||
|
||||
```powershell
|
||||
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
|
||||
```
|
||||
|
||||
Cette commande active WSL
|
||||
|
||||
```powershell
|
||||
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
|
||||
```
|
||||
|
||||
Cette commande permet d'autoriser le démarrage des machines signées par Microsoft.
|
||||
|
||||
2. Redémarrez votre ordinateur.
|
||||
|
||||
3. Téléchargez [ce fichier](https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi) et suivez les instructions d'installation.
|
||||
|
||||
4. Ouvrez votre fenêtre PowerShell comme avant et tapez:
|
||||
|
||||
```powershell
|
||||
wsl --set-default-version 2
|
||||
```
|
||||
|
||||
5. Téléchargez [Ubuntu](https://www.microsoft.com/store/apps/9n6svws3rx71) depuis le Microsoft store. Vous pouvez aussi installer [Debian](https://www.microsoft.com/store/productI9MSVKQC78PK6) à la place.
|
||||
|
||||
WSL est maintenant installé.
|
||||
|
||||
6. Installez maintenant la version pour ARM de GCC.
|
||||
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential git imagemagick libx11-dev libxext-dev libfreetype6-dev libpng-dev libjpeg-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
|
||||
```
|
||||
|
||||
### Installation d'usbipd pour connecter la calculatrice à WSL (facultatif)
|
||||
|
||||
Pour connecter la calculatrice, il faut installer cet [outil](hthttps://github.com/dorssel/usbipd-win/releases/download/v5.0.0/usbipd-win_5.0.0_x64.msi). Il permet de connecter des périphériques par Internet. Suivez les instructions pour l'installer.
|
||||
|
||||
#### Ubuntu
|
||||
|
||||
1. Dans un terminal WSL Ubuntu, tapez :
|
||||
|
||||
```bash
|
||||
sudo apt install linux-tools-generic hwdata
|
||||
```
|
||||
|
||||
<!-- 2. Editez /etc/sudoers pour que l'on puisse utiliser la commande usbip. Sur Ubuntu, cela est fait de cette manière :
|
||||
|
||||
```bash
|
||||
sudo visudo
|
||||
```
|
||||
|
||||
3. Ajoutez `/usr/lib/linux-tools/5.4.0-77-generic` au début du secure_path. Après édition, la ligne devrait ressembler à:
|
||||
`Defaults secure_path="/usr/lib/linux-tools/5.4.0-77-generic:/usr/local/sbin:..."` -->
|
||||
|
||||
#### Debian
|
||||
|
||||
1.Si vous utilisez Debian, lancez cette commande:
|
||||
|
||||
```bash
|
||||
sudo apt install usbip hwdata usbutils
|
||||
```
|
||||
|
||||
### Pour connecter la calculatrice à WSL
|
||||
|
||||
1. Ouvrez à nouveau un PowerShell en mode administrateur et tapez :
|
||||
|
||||
```powershell
|
||||
usbipd list
|
||||
```
|
||||
|
||||
Ceci va lister les périphériques USB connectés à l'ordinateur. Regardez le BUSID de votre "Numworks Calculator".
|
||||
|
||||
2. Maintenant, lancez cette commande en remplaçant <BUSID> par celui de votre calculatrice :
|
||||
|
||||
```powershell
|
||||
usbipd bind --busid <BUSID>
|
||||
usbipd attach --wsl --busid <BUSID>
|
||||
```
|
||||
|
||||
Le mot de passe de votre machine WSL vous sera demandé.
|
||||
|
||||
Vous pouvez aller à l'étape 2.
|
||||
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
<br>
|
||||
|
||||
### 2. Récupérer le code source
|
||||
|
||||
Le code source est disponible dans une repository git. Récupérez-le de cette manière :
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
|
||||
cd Upsilon
|
||||
git checkout upsilon-dev
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### 3. Choisissez le système à compiler
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>Model n0100</b></summary>
|
||||
|
||||
(note: vous pouvez changer l'argument `EPSILON_I18N=en` avec `fr`, `nl`, `pt`, `it`, `de`, `es` or `hu`).
|
||||
|
||||
```bash
|
||||
make MODEL=n0100 clean
|
||||
make MODEL=n0100 EPSILON_I18N=en OMEGA_USERNAME="{Votre nom, maximum 15 caractères}" -j4
|
||||
```
|
||||
|
||||
Maintenant, lancez soit:
|
||||
|
||||
```bash
|
||||
make MODEL=n0100 epsilon_flash
|
||||
```
|
||||
|
||||
pour directement flasher la calculatrice après avoir appuyé simultanément sur `reset` et `6` et avoir branché la calculatrice à l'ordinateur.
|
||||
|
||||
<br>
|
||||
|
||||
soit:
|
||||
|
||||
```bash
|
||||
make MODEL=n0100 OMEGA_USERNAME="" binpack -j4
|
||||
```
|
||||
|
||||
pour compiler les binpacks que vous pouvez distribuer et flasher depuis le [WebDFU de TI-Planet](https://ti-planet.github.io/webdfu_numworks/n0100/).
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>Model n0110</b></summary>
|
||||
|
||||
Le bootloader vous permet d'installer 2 firmwares dans des "slots" séparés. Dans ce cas les applications externes ne pourront pas utiliser toute la mémoire mais la moitié. Si un seul slot est utilisé, le bootloader permettra d'utiliser toute la mémoire. Sans bootloader, les apps externes peuvent utiliser toute la mémoire.
|
||||
|
||||
<details>
|
||||
<summary>Bootloader</summary>
|
||||
|
||||
Votre calculatrice doit être flashé avec le bootloader d'[Upsilon](https://getupsilon.web.app) ou d'[Omega](https://getomega.dev).
|
||||
Compilez avec:
|
||||
|
||||
```bash
|
||||
make clean
|
||||
make OMEGA_USERNAME="{Votre nom, max 15 caractères}" -j4
|
||||
```
|
||||
|
||||
Ensuite lancez soit:
|
||||
|
||||
```bash
|
||||
make epsilon.A_flash
|
||||
```
|
||||
|
||||
pour flasher le slot actuel ou pour flasher par le flasher du booloader avec RESET, puis 4 (flash) et 1 (flash slots) pour flasher n'importe quel slot.
|
||||
|
||||
<br>
|
||||
|
||||
soit:
|
||||
|
||||
```bash
|
||||
make OMEGA_USERNAME="{Votre nom, max 15 caractères}" binpack -j4
|
||||
```
|
||||
|
||||
pour compiler les binpacks que vous pouvez distribuer et flasher depuis le [WebDFU de TI-Planet](https://ti-planet.github.io/webdfu_numworks/n0100/). Vous les trouverez dans `output/release/device/bootloader/`.
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Model n0110 sans bootloader (obsolète, utilisez le bootloader à la place pour la protection contre Epsilon)</summary>
|
||||
Compilez avec:
|
||||
|
||||
```bash
|
||||
make MODEL=n0110 clean
|
||||
make MODEL=n0110 OMEGA_USERNAME="{Votre nom, max 15 caractères}" -j4
|
||||
```
|
||||
|
||||
Ensuite lancez soit:
|
||||
|
||||
```bash
|
||||
make MODEL=n0110 epsilon_flash
|
||||
```
|
||||
|
||||
pour directement flasher la calculatrice après avoir appuyé simultanément sur `RESET` et `6` et avoir branché la calculatrice à l'ordinateur.
|
||||
<br>
|
||||
|
||||
soit:
|
||||
|
||||
```bash
|
||||
make MODEL=n0110 OMEGA_USERNAME="{Votre nom, max 15 caractères}" binpack -j4
|
||||
```
|
||||
|
||||
pour compiler les binpacks que vous pouvez distribuer et flasher depuis le [WebDFU de TI-Planet](https://ti-planet.github.io/webdfu_numworks/n0100/). Vous les trouverez dans `output/release/device/n0110/`.
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>Simulateur Natif</b></summary>
|
||||
|
||||
Lancez cette commande:
|
||||
```bash
|
||||
make clean
|
||||
```
|
||||
Vous pouvez soit choisir d'utiliser la commmande qui détectera automatiquement votre plateforme:
|
||||
```bash
|
||||
make PLATFORM=simulator
|
||||
```
|
||||
Ou choisir une commande qui correspond à votre plateforme:
|
||||
```bash
|
||||
make PLATFORM=simulator TARGET=android
|
||||
make PLATFORM=simulator TARGET=ios
|
||||
make PLATFORM=simulator TARGET=macos
|
||||
make PLATFORM=simulator TARGET=web
|
||||
make PLATFORM=simulator TARGET=windows
|
||||
make PLATFORM=simulator TARGET=3ds
|
||||
```
|
||||
|
||||
Vous trouverez les fichiers du simulateur dans `output/release/simulator/`.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>Simulateur web</b></summary>
|
||||
|
||||
D'abord, installez emsdk :
|
||||
|
||||
```bash
|
||||
git clone https://github.com/emscripten-core/emsdk.git
|
||||
cd emsdk
|
||||
./emsdk install 1.40.1
|
||||
./emsdk activate 1.40.1
|
||||
source emsdk_env.sh
|
||||
```
|
||||
|
||||
Puis, compilez Upsilon :
|
||||
|
||||
```bash
|
||||
make clean
|
||||
make PLATFORM=simulator TARGET=web OMEGA_USERNAME="{Votre nom, maximum 15 caractères}" -j4
|
||||
```
|
||||
|
||||
Le simulateur se trouve dans `output/release/simulator/web/simulator.zip`
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>Simulateur Android</b></summary>
|
||||
|
||||
Assurez-vous d'avoir JDK 25 d'installé.
|
||||
Ensuite, téléchargez la toolchain Android version r21e comme suit :
|
||||
```
|
||||
export ANDROID_HOME=$PWD/android-sdk
|
||||
wget -nv https://gitlab.com/fdroid/sdkmanager/-/raw/master/sdkmanager.py
|
||||
python3 sdkmanager.py --licenses
|
||||
python3 sdkmanager.py --install "ndk-bundle;r21e"
|
||||
```
|
||||
Il ne vous reste plus qu'à lancer cette commande pour compiler Upsilon.
|
||||
```
|
||||
make -j$(nproc) PLATFORM=simulator TARGET=android
|
||||
```
|
||||
Le fichier compilé nommé `epsilon.apk` sera celui à installer sur le téléphone depuis votre gestionnaire de fichier. Fonctionne normalement à partir de Android 4.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>Simulateur pour 3DS</b></summary>
|
||||
|
||||
Il vous faut devkitPro et devkitARM installés et dans votre path (les instructions sont [ici](https://devkitpro.org/wiki/Getting_Started))
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
|
||||
cd Upsilon
|
||||
git checkout --recursive upsilon-dev
|
||||
make PLATFORM=simulator TARGET=3ds -j
|
||||
```
|
||||
|
||||
Vous pouvez ensuite mettre epsilon.3dsx sur une carte SD pour le lancer depuis le HBC ou utilisez 3dslink pour le lancer via le réseau:
|
||||
|
||||
```bash
|
||||
3dslink output/release/simulator/3ds/epsilon.3dsx -a <3DS' IP ADDRESS>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<br>
|
||||
|
||||
Important: n'oubliez pas l'argument `--recursive` parce qu'Upsilon dépend de submodules.
|
||||
Aussi, vous pouvez changer le nombre de processus de compilation en parallèles en changeant le nombre après l'argument `-j`.
|
||||
N'oubliez pas de mettre votre nom à la place `{Votre nom, maximum 15 caractères}`. Si vous n'en voulez pas, enlevez l'argument `OMEGA_USERNAME`.
|
||||
|
||||
Si vous avez besoin d'aide, n'hésitez pas à rejoindre notre serveur Discord : <https://discord.gg/Q9buEMduXG>
|
||||
|
||||
<a href="https://discord.gg/Q9buEMduXG"><p align="center"><img alt="Omega Banner Discord" src="https://user-images.githubusercontent.com/12123721/86287349-54ef5800-bbe8-11ea-80c1-34eb1f93eebd.png" /></p></a>
|
||||
---
|
||||
|
||||
## Liens utiles
|
||||
|
||||
- [Upsilon-External (pour installer des applications supplémentaires et des fonds d'écran)](https://upsilonnumworks.github.io/Upsilon-External/)
|
||||
- [Documentation d'Ulab](https://micropython-ulab.readthedocs.io/en/latest/)
|
||||
|
||||
## Contribution
|
||||
|
||||
Pour contribuer, merci de lire le [Wiki d'Omega](https://github.com/Omega-Numworks/Omega/wiki/Contributing), les mêmes règles s'appliquent ici.
|
||||
|
||||
## Les autres projets
|
||||
|
||||
Les anciens projets d'Omega, avant sa fermeture, qui ont été utilisés pour ce projet
|
||||
|
||||
- [Omega Themes](https://github.com/Omega-Numworks/Omega-Themes)
|
||||
- [Omega Website](https://github.com/Omega-Numworks/Omega-Website)
|
||||
- [Omega RPN `APP`](https://github.com/Omega-Numworks/Omega-RPN)
|
||||
- [Omega Atomic `APP`](https://github.com/Omega-Numworks/Omega-Atomic)
|
||||
- [Omega Design](https://github.com/Omega-Numworks/Omega-Design)
|
||||
- [Omega Discord Bot](https://github.com/Omega-Numworks/Omega-Discord-Bot)
|
||||
- [Omega App Template `BETA`](https://github.com/Omega-Numworks/Omega-App-Template)
|
||||
- [External Apps](https://github.com/Omega-Numworks/External-Apps)
|
||||
|
||||
## À propos d'Epsilon
|
||||
|
||||
Upsilon est un fork d'Omega, visant a continuer le projet des OS utilisateurs pour NumWorks.
|
||||
|
||||
Omega est un fork d'Epsilon, un système d'exploitation performant pour calculatrices graphiques. Il inclut huit applications pour les mathématiques de lycée et d'études supérieures.
|
||||
|
||||
Vous pouvez essayer Epsilon depuis votre navigateur sur le [simulateur en ligne](https://www.numworks.com/simulator/).
|
||||
|
||||
## Licence
|
||||
|
||||
NumWorks est une marque déposée de NumWorks SAS, 24 Rue Godot de Mauroy, 75009 Paris, France.
|
||||
Nintendo et Nintendo 3DS sont des marques déposées de Nintendo of America Inc, 4600 150th Ave NE, Redmond, WA 98052, Etats-Unis.
|
||||
NumWorks SAS et Nintendo of America Inc ne sont en aucun cas associés avec ce projet.
|
||||
|
||||
- NumWorks Epsilon est disponible sous [licence CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.fr).
|
||||
- Omega est disponible sous [licence CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.fr).
|
||||
- Upsilon est disponible sous [licence CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.fr).
|
||||
535
README.md
535
README.md
@@ -1,166 +1,521 @@
|
||||
<p align="center"><img src="https://user-images.githubusercontent.com/12123721/87953533-75a22380-caab-11ea-8cde-c40291c4a9ae.png" /></p>
|
||||
<p align="center"><img src="https://github.com/Laporte12974/UpsilonDesign/blob/89a15953ae128aef8aa7d066dcaaf8d5c70f02a5/UPSILogo.png" /></p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/"><img alt="cc by-nc-sa 4.0" src="https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-525252.svg?labelColor=292929&logo=creative%20commons&style=for-the-badge" /></a>
|
||||
<a href="https://github.com/Omega-Numworks/Omega/issues"><img alt="Issues" src="https://img.shields.io/github/issues/Omega-Numworks/Omega.svg?labelColor=292929&logo=git&style=for-the-badge" /></a>
|
||||
<a href="https://github.com/UpsilonNumworks/Upsilon/issues"><img alt="Issues" src="https://img.shields.io/github/issues/UpsilonNumworks/Upsilon.svg?labelColor=292929&logo=git&style=for-the-badge" /></a>
|
||||
<br/>
|
||||
<a href="https://discord.gg/X2TWhh9"><img alt="Discord" src="https://img.shields.io/discord/663420259851567114?color=blue&labelColor=292929&label=chat%20-%20discord&logo=discord&style=for-the-badge" /></a>
|
||||
<a href="https://discord.gg/hnEqPzAJzn"><img alt="Discord" src="https://img.shields.io/discord/663420259851567114?color=blue&labelColor=292929&label=chat%20-%20discord&logo=discord&style=for-the-badge" /></a>
|
||||
</p>
|
||||
|
||||
> 🇫🇷 Vous ne comprenez pas l'anglais ? Vous êtes francophone ? Regardez le [*LISEZ-MOI* français](./README.fr.md) ! 🇫🇷
|
||||
|
||||
## About
|
||||
|
||||
Omega is a fork of Numworks' Epsilon, the OS that runs on their calculator, which brings many features to it. Omega is for the people who want to add features to the calculator, but cannot because they have been rejected by Numworks (for reasons that are 100% understandable!).
|
||||
Upsilon is a fork of Omega, an user-made OS that runs on the NumWorks calculator, which brings many features to it, but was discontinued because of a policy change from NumWorks. Upsilon is for the people who want to see a future for user-made OSes for NumWorks, even after the closure and archiving of Omega.
|
||||
|
||||
## Some new features
|
||||
- Adding symbolic calculation back into the calculator
|
||||
- An app for RPN
|
||||
- A periodic table app + all of the molar masses for the elements in the toolbox
|
||||
- More steps for brightness (16 instead of 5)
|
||||
- ~~32 KB Python heap instead of 16 KB~~ Now available on Epsilon `>=13.2.0`!
|
||||
- And more...
|
||||
### Some new features
|
||||
|
||||
The main new features are listed [here](https://github.com/Omega-Numworks/Omega/wiki/Main-features), and the complete changelog can be found [here](https://github.com/Omega-Numworks/Omega/wiki/Changelog).
|
||||
- Enhancements for the Kandinsky python module
|
||||
- Support for wallpapers
|
||||
- External apps
|
||||
- A custom theme
|
||||
- Operator overload for python
|
||||
- Improvements for the Periodic table application
|
||||
- *And everything that has been added to Omega before its termination!* [See Omega's changelog here](https://github.com/Omega-Numworks/Omega/wiki/Changelog) | [Main Omega features + screenshots](https://github.com/Omega-Numworks/Omega/wiki/Main-features).
|
||||
|
||||
<br>
|
||||
|
||||
## Installation
|
||||
|
||||
### Automatic
|
||||
### Installer
|
||||
|
||||
You can install Omega automatically on our website [here](https://getomega.web.app/) in the "install" page.
|
||||
|
||||
<a href="https://getomega.web.app"><p align="center"><img alt="Omega Banner Discord" src="https://user-images.githubusercontent.com/12123721/86352956-e9000480-bc66-11ea-82b7-79fd7e56fa27.png" /></p></a>
|
||||
Go to the [Upsilon website](https://getupsilon.web.app/) to the "Install" section.
|
||||
If your calculator is recognized, contains a version of Epsilon lower than 16 and your browser accepts WebUSB, the page will suggest you to install Upsilon.
|
||||
Do not disconnect your calculator until the installation is complete.
|
||||
|
||||
### Manual
|
||||
|
||||
First of all, follow **step 1** [here](https://www.numworks.com/resources/engineering/software/build/). Then:
|
||||
*You can refer to this [website](https://www.numworks.com/resources/engineering/software/build/) for the first step if you get errors.*
|
||||
|
||||
### 1. Install SDK
|
||||
|
||||
<br>
|
||||
|
||||
<details>
|
||||
<summary><b>Model n0100</b></summary>
|
||||
|
||||
<summary><b>1.1 Linux</b></summary>
|
||||
|
||||
<br>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Debian or Ubuntu</summary>
|
||||
|
||||
<br>
|
||||
|
||||
You just have to install dependencies by running these command with superuser privileges in a Terminal:
|
||||
|
||||
```bash
|
||||
apt-get install build-essential git imagemagick libx11-dev libxext-dev libfreetype6-dev libpng-dev libjpeg-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
|
||||
```
|
||||
|
||||
And there you can go to step 2!
|
||||
|
||||
<br>
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Fedora</summary>
|
||||
|
||||
<br>
|
||||
|
||||
To install all dependencies:
|
||||
|
||||
```bash
|
||||
dnf install make automake gcc gcc-c++ kernel-devel git ImageMagick libX11-devel libXext-devel freetype-devel libpng-devel libjpeg-devel pkg-config arm-none-eabi-gcc-cs arm-none-eabi-gcc-cs-c++
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>Nix or Nixos</summary>
|
||||
|
||||
<br>
|
||||
|
||||
To install all dependencies:
|
||||
|
||||
```bash
|
||||
nix-shell -p gcc libpng libjpeg xorg.libX11 pkg-config freetype xorg.libXext python3 imagemagick python310Packages.lz4 python310Packages.pypng python310Packages.pypng gcc-arm-embedded
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
</details>
|
||||
|
||||
<br>
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>1.2 Mac</b></summary>
|
||||
|
||||
<br>
|
||||
|
||||
It's recommended to use [Homebrew](https://brew.sh/). Once it's installed, just run:
|
||||
|
||||
```bash
|
||||
brew install numworks/tap/epsilon-sdk
|
||||
```
|
||||
|
||||
and it will install all dependencies.
|
||||
|
||||
<br>
|
||||
|
||||
And there you can go to step 2!
|
||||
|
||||
<br>
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>1.3 Windows</b></summary>
|
||||
|
||||
<br>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>With Msys2/Mingw (officialized by NumWorks but with a lot of bugs)</summary>
|
||||
|
||||
[Msys2](https://www.msys2.org/) environment is recommended by NumWorks to get most of the required tools on Windows easily. It's where you'll paste all the commands of this tutorial. Once it's installed, paste these commands into the Msys2 terminal.
|
||||
|
||||
```bash
|
||||
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-freetype mingw-w64-x86_64-pkg-config mingw-w64-x86_64-libusb git make python
|
||||
echo "export PATH=/mingw64/bin:$PATH" >> .bashrc
|
||||
```
|
||||
|
||||
Next, you'll need to install the [GCC toolchain for ARM](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads). When prompted for an install location, choose `C:\msys64\home\User\gcc-arm\`. You'll then need to add this folder to your $PATH. Just enter:
|
||||
|
||||
```bash
|
||||
echo "export PATH=$PATH:$HOME/gcc-arm/bin" >> .bashrc
|
||||
```
|
||||
|
||||
Just restart terminal and you can go to step 2!
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
<summary>With WSL 2</summary>
|
||||
|
||||
You need a Windows version >= 1903.
|
||||
|
||||
#### WSL Installation
|
||||
|
||||
1. Use simultaneously Win + X keys and then click on "admin powershell".
|
||||
|
||||
```powershell
|
||||
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
|
||||
```
|
||||
|
||||
This command activate WSL functionalities.
|
||||
|
||||
```powershell
|
||||
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
|
||||
```
|
||||
|
||||
This one allows virtual machines developed by Microsoft.
|
||||
|
||||
2. Restart your computer.
|
||||
|
||||
3. Download [this file](https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi) and follow instructions.
|
||||
|
||||
4. Now open powershell admin like before and type:
|
||||
|
||||
```powershell
|
||||
wsl --set-default-version 2
|
||||
```
|
||||
|
||||
5. Download [Ubuntu](https://www.microsoft.com/store/apps/9n6svws3rx71) from Microsoft store.
|
||||
|
||||
WSL is now installed.
|
||||
|
||||
6. Then Install GCC cross compiler for ARM. In your Ubuntu teminal, run:
|
||||
<!-- TODO: Test if `wsl --install` works better, and if WSL2 has not became the
|
||||
default -->
|
||||
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install build-essential git imagemagick libx11-dev libxext-dev libfreetype6-dev libpng-dev libjpeg-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
|
||||
```
|
||||
|
||||
### Usbipd installation to connect your calculator
|
||||
|
||||
If you want to connect to the calculator, you have to connect to install this
|
||||
[tool](https://github.com/dorssel/usbipd-win/releases/download/v5.0.0/usbipd-win_5.0.0_x64.msi).
|
||||
This will allow you to connect WSL to the calculator through internet. Follow
|
||||
the on screen information to install.
|
||||
|
||||
#### Ubuntu
|
||||
|
||||
1. In a WSL Ubuntu command prompt, type:
|
||||
|
||||
```bash
|
||||
sudo apt install linux-tools-generic hwdata
|
||||
```
|
||||
|
||||
<!-- 2. Edit /etc/sudoers so that root can find the usbip command. On Ubuntu, run this command.
|
||||
|
||||
```bash
|
||||
sudo visudo
|
||||
```
|
||||
|
||||
3. Add `/usr/lib/linux-tools/5.4.0-77-generic` to the beginning of secure_path. After editing, the line should look similar to this.
|
||||
`Defaults secure_path="/usr/lib/linux-tools/5.4.0-77-generic:/usr/local/sbin:..."` -->
|
||||
|
||||
#### Debian
|
||||
|
||||
1. If you use Debian for your WSL distro, use this command instead:
|
||||
|
||||
```bash
|
||||
sudo apt install usbip hwdata usbutils
|
||||
```
|
||||
|
||||
And that's all for installation and set up.
|
||||
|
||||
### To connect your calculator
|
||||
|
||||
1. Open an admin PowerShell and type:
|
||||
|
||||
```powershell
|
||||
usbipd list
|
||||
```
|
||||
|
||||
This will list your USB devices connected. Look at the BUSID column and remember the one for your calculator (it should be called "Numworks Calculator").
|
||||
2. Now run this command replacing `<BUSID>` by your calculator's USB port id:
|
||||
|
||||
```powershell
|
||||
usbipd bind --busid <BUSID>
|
||||
usbipd attach --wsl --busid <BUSID>
|
||||
|
||||
```
|
||||
git clone --recursive https://github.com/Omega-Numworks/Omega.git
|
||||
cd Omega
|
||||
git checkout omega-master
|
||||
|
||||
It will ask you to type your WSL's password and will connect your calculator to WSL.
|
||||
|
||||
You can now go to step 2!
|
||||
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
<br>
|
||||
|
||||
### 2. Set up repo
|
||||
|
||||
Clone repo and use 'upsilon-dev' branch by pasting these two commands:
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
|
||||
cd Upsilon
|
||||
git checkout upsilon-dev
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### 3. Choose the target
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>Model n0100</b></summary>
|
||||
|
||||
(note: you can change the `EPSILON_I18N=en` flag to `fr`, `nl`, `pt`, `it`, `de`, `es` or `hu`).
|
||||
|
||||
```bash
|
||||
make MODEL=n0100 clean
|
||||
make MODEL=n0100 OMEGA_USERNAME="{Your name, max 15 characters}" -j4
|
||||
make MODEL=n0100 EPSILON_I18N=en OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
|
||||
```
|
||||
|
||||
Now, run either:
|
||||
|
||||
```bash
|
||||
make MODEL=n0100 epsilon_flash
|
||||
```
|
||||
|
||||
Important: Don't forget the `--recursive` tag, because Omega relies on submodules.
|
||||
Also, you can change the number of processes that run in parallel during the build by changing the value of the `-j` flag.
|
||||
|
||||
to directly flash the calculator after pressing simultaneously `reset` and `6` buttons and plugging in.
|
||||
|
||||
<br>
|
||||
|
||||
or:
|
||||
|
||||
```bash
|
||||
make MODEL=n0100 OMEGA_USERNAME="" binpack -j$(nproc)
|
||||
```
|
||||
|
||||
to make binpack which you can flash to the calculator from [TI-Planet's WebDFU](https://ti-planet.github.io/webdfu_numworks/n0100/). Binpacks are a great way to share a custom build of Upsilon to friends.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Model n0110</b></summary>
|
||||
|
||||
```
|
||||
git clone --recursive https://github.com/Omega-Numworks/Omega.git
|
||||
cd Omega
|
||||
git checkout omega-master
|
||||
<summary><b>Model n0110</b></summary>
|
||||
|
||||
The bootloader allows you to install 2 firmwares in separated "slots". If so, external apps won't have all the space but half. Bootloader will allow use of all of the memory if only one slot is flashed. In legacy mode, external apps use all the space available.
|
||||
|
||||
<details>
|
||||
<summary>Bootloader</summary>
|
||||
|
||||
Your calculator must already have been flashed with [Upsilon](https://getupsilon.web.app)'s or [Omega](https://getomega.dev)'s bootloader.
|
||||
Then, build with:
|
||||
|
||||
```bash
|
||||
make clean
|
||||
make OMEGA_USERNAME="{Your name, max 15 characters}" -j4
|
||||
make epsilon_flash
|
||||
make OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
|
||||
```
|
||||
|
||||
Important: Don't forget the `--recursive` tag, because Omega relies on submodules.
|
||||
Also, you can change the number of processes that run in parallel during the build by changing the value of the `-j` flag.
|
||||
|
||||
Now, run either:
|
||||
|
||||
```bash
|
||||
make epsilon.A_flash
|
||||
```
|
||||
|
||||
to directly flash the calculator into the current slot, or thought bootloader's slot flasher with RESET, then 4 (flash), and 1 (flash slots) for other slots.
|
||||
|
||||
<br>
|
||||
|
||||
or:
|
||||
|
||||
```bash
|
||||
make OMEGA_USERNAME="" binpack -j$(nproc)
|
||||
```
|
||||
|
||||
to make binpack which you can flash to the calculator from [TI-Planet's webDFU](https://ti-planet.github.io/webdfu_numworks/n0110/). You'll find them at `output/release/device/bootloader/`. Binpacks are a great way to share a custom build of Upsilon to friends.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Bin files</b></summary>
|
||||
|
||||
These can be used to distribute Omega (so that it can be flashed by anyone with [Webdfu_Numworks](https://ti-planet.github.io/webdfu_numworks/)).
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Model N0110 legacy (deprecated, use bootloader instead for Epsilon protection)</summary>
|
||||
|
||||
```bash
|
||||
make MODEL=n0110 clean
|
||||
make MODEL=n0110 OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
|
||||
```
|
||||
git clone --recursive https://github.com/Omega-Numworks/Omega.git
|
||||
cd Omega
|
||||
git checkout omega-master
|
||||
|
||||
Now, run either:
|
||||
|
||||
```bash
|
||||
make MODEL=n0110 epsilon_flash
|
||||
```
|
||||
|
||||
to directly flash the calculator after pressing simultaneously `reset` and `6` buttons and plugging in.
|
||||
|
||||
<br>
|
||||
|
||||
or:
|
||||
|
||||
```bash
|
||||
make MODEL=n0110 OMEGA_USERNAME="" binpack -j$(nproc)
|
||||
```
|
||||
|
||||
to make binpack which you can flash to the calculator from [Ti-Planet's WebDFU](https://ti-planet.github.io/webdfu_numworks/n0110/). You'll find them at `output/release/device/bootloader/`. Binpacks are a great way to share a custom build of Upsilon to friends.
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
|
||||
<summary><b>Native simulator</b></summary>
|
||||
|
||||
Run this command:
|
||||
```bash
|
||||
make clean
|
||||
make MODEL=n0100 OMEGA_USERNAME="" -j8
|
||||
make MODEL=n0100 OMEGA_USERNAME="" binpack -j8
|
||||
make OMEGA_USERNAME="" -j8
|
||||
make OMEGA_USERNAME="" binpack -j8
|
||||
```
|
||||
You can either build using the following command that will automatically detect your platform:
|
||||
```bash
|
||||
make PLATFORM=simulator
|
||||
```
|
||||
or, choose the command corresponding to your platform:
|
||||
```bash
|
||||
make PLATFORM=simulator TARGET=android
|
||||
make PLATFORM=simulator TARGET=ios
|
||||
make PLATFORM=simulator TARGET=macos
|
||||
make PLATFORM=simulator TARGET=web
|
||||
make PLATFORM=simulator TARGET=windows
|
||||
make PLATFORM=simulator TARGET=3ds
|
||||
```
|
||||
|
||||
Important: Don't forget the `--recursive` tag, because Omega relies on submodules.
|
||||
Also, you can change the number of processes that run in parallel during the build by changing the value of the `-j` flag.
|
||||
|
||||
You'll find simulator files in `output/release/simulator/`.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary><b>Web simulator</b></summary>
|
||||
|
||||
|
||||
<summary><b>Web simulator</b></summary>
|
||||
|
||||
First, install emsdk :
|
||||
|
||||
```
|
||||
```bash
|
||||
git clone https://github.com/emscripten-core/emsdk.git
|
||||
cd emsdk
|
||||
./emsdk install latest-fastcomp
|
||||
./emsdk activate latest-fastcomp
|
||||
./emsdk install 1.40.1
|
||||
./emsdk activate 1.40.1
|
||||
source emsdk_env.sh
|
||||
```
|
||||
|
||||
Then, compile Omega :
|
||||
Then, compile Upsilon :
|
||||
|
||||
```
|
||||
git clone --recursive https://github.com/Omega-Numworks/Omega.git
|
||||
cd Omega
|
||||
git checkout omega-master
|
||||
```bash
|
||||
make clean
|
||||
make PLATFORM=simulator TARGET=web OMEGA_USERNAME="{Your name, max 15 characters}" -j4
|
||||
make PLATFORM=simulator TARGET=web OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
|
||||
```
|
||||
|
||||
The simulator is now in `output/release/simulator/web/simulator.zip`
|
||||
|
||||
Important: Don't forget the `--recursive` tag, because Omega relies on submodules.
|
||||
Also, you can change the number of processes that run in parallel during the build by changing the value of the `-j` flag.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>3DS Simulator</b></summary>
|
||||
|
||||
|
||||
<summary><b>3DS Simulator</b></summary>
|
||||
|
||||
You need devkitPro and devkitARM installed and in your path (instructions [here](https://devkitpro.org/wiki/Getting_Started))
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
|
||||
cd Upsilon
|
||||
git checkout upsilon-dev
|
||||
make PLATFORM=simulator TARGET=3ds -j$(nproc)
|
||||
```
|
||||
git clone --recursive https://github.com/Omega-Numworks/Omega.git
|
||||
cd Omega
|
||||
git checkout --recursive omega-dev
|
||||
make PLATFORM=simulator TARGET=3ds -j
|
||||
```
|
||||
|
||||
You can then put epsilon.3dsx on a SD card to run it from the HBC or use 3dslink to launch it over the network:
|
||||
```
|
||||
|
||||
```bash
|
||||
3dslink output/release/simulator/3ds/epsilon.3dsx -a <3DS' IP ADDRESS>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
If you need help, you can join our Discord server here : https://discord.gg/X2TWhh9
|
||||
<details>
|
||||
|
||||
<summary><b>Android Simulator</b></summary>
|
||||
|
||||
Make sure you have JDK 25 installed.
|
||||
Then, download the Android toolchain r21e as following :
|
||||
```
|
||||
export ANDROID_HOME=$PWD/android-sdk
|
||||
wget -nv https://gitlab.com/fdroid/sdkmanager/-/raw/master/sdkmanager.py
|
||||
python3 sdkmanager.py --licenses
|
||||
python3 sdkmanager.py --install "ndk-bundle;r21e"
|
||||
```
|
||||
All you have to do is run this command to compile Upsilon.
|
||||
```
|
||||
make -j$(nproc) PLATFORM=simulator TARGET=android
|
||||
```
|
||||
The compiled file named `epsilon.apk` will be the one to install on the phone from your file manager. Shoudl work on Android 4.1+.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Casio fx-CG-series Port</b></summary>
|
||||
|
||||
First, install gint and fxsdk along with a cross compiler for the calculator. There are instructions for this (in French, but Google Translate works well enough) [here](https://www.planet-casio.com/Fr/forums/topic16614-last-giteapc-installer-et-mettre-a-jour-automatiquement-des-projets-gitea.html).
|
||||
|
||||
Next:
|
||||
```bash
|
||||
git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
|
||||
cd Omega
|
||||
git checkout upsilon-dev
|
||||
make PLATFORM=simulator TARGET=fxcg -j$(nproc)
|
||||
```
|
||||
Then copy the file at `./output/release/simulator/fxcg/epsilon.g3a` to the calculator over USB.
|
||||
|
||||
</details>
|
||||
|
||||
Important: Don't forget the `--recursive` tag, because Upsilon relies on submodules.
|
||||
Also, you can change the number of processes that run in parallel during the build by changing the value of the `-j` flag.
|
||||
Don't forget to put your pseudo instead of `{your pseudo, max 15 char}`. If you don't want one, just remove the `OMEGA_USERNAME=""` argument.
|
||||
|
||||
<br>
|
||||
|
||||
If you need help, you can join our Discord server here : <https://discord.gg/NFvzdCBTQn>
|
||||
|
||||
<a href="https://discord.gg/NFvzdCBTQn"><p align="center"><img alt="Omega Banner Discord" src="https://user-images.githubusercontent.com/12123721/86287349-54ef5800-bbe8-11ea-80c1-34eb1f93eebd.png" /></p></a>
|
||||
|
||||
<a href="https://discord.gg/X2TWhh9"><p align="center"><img alt="Omega Banner Discord" src="https://user-images.githubusercontent.com/12123721/86287349-54ef5800-bbe8-11ea-80c1-34eb1f93eebd.png" /></p></a>
|
||||
---
|
||||
|
||||
## Useful links
|
||||
|
||||
- [Upsilon external (to install additional apps and wallpapers)](https://upsilonnumworks.github.io/Upsilon-External/)
|
||||
- [Ulab documentation](https://micropython-ulab.readthedocs.io/en/latest/)
|
||||
|
||||
## Contributing
|
||||
|
||||
To contribute, please refer to the [Wiki](https://github.com/Omega-Numworks/Omega/wiki/Contributing)
|
||||
|
||||
## Branches
|
||||
|
||||
* `omega-master` : stable releases
|
||||
* `omega-dev` : beta releases
|
||||
* `omega-hotfix` : developers only, branch to fix issues
|
||||
To contribute, please refer to [Omega's Wiki](https://github.com/Omega-Numworks/Omega/wiki/Contributing), the same rules apply here.
|
||||
|
||||
## Related repositories
|
||||
|
||||
* [Omega Themes](https://github.com/Omega-Numworks/Omega-Themes)
|
||||
* [Omega Website](https://github.com/Omega-Numworks/Omega-Website)
|
||||
* [Omega RPN `APP`](https://github.com/Omega-Numworks/Omega-RPN)
|
||||
* [Omega Atom `APP`](https://github.com/Omega-Numworks/Omega-Atom)
|
||||
* [Omega Design](https://github.com/Omega-Numworks/Omega-Design)
|
||||
* [Omega App Template `BETA`](https://github.com/Omega-Numworks/Omega-App-Template)
|
||||
Here are the main links toward Omega's different websites and repositories, that have been used for the creation of Upsilon.
|
||||
|
||||
- [Omega Themes](https://github.com/Omega-Numworks/Omega-Themes)
|
||||
- [Omega Website](https://github.com/Omega-Numworks/Omega-Website)
|
||||
- [Omega RPN `APP`](https://github.com/Omega-Numworks/Omega-RPN)
|
||||
- [Omega Atomic `APP`](https://github.com/Omega-Numworks/Omega-Atomic)
|
||||
- [Omega Design](https://github.com/Omega-Numworks/Omega-Design)
|
||||
- [Omega Discord Bot](https://github.com/Omega-Numworks/Omega-Discord-Bot)
|
||||
- [Omega App Template `BETA`](https://github.com/Omega-Numworks/Omega-App-Template)
|
||||
- [External Apps](https://github.com/Omega-Numworks/External-Apps)
|
||||
|
||||
## About Epsilon
|
||||
|
||||
Upsilon is a fork of Omega, after the project's discontinuation.
|
||||
|
||||
Omega is a fork of Epsilon, a high-performance graphing calculator operating system. It includes eight apps that cover the high school mathematics curriculum.
|
||||
|
||||
You can try Epsilon straight from your browser in the [online simulator](https://www.numworks.com/simulator/).
|
||||
@@ -169,7 +524,9 @@ You can try Epsilon straight from your browser in the [online simulator](https:/
|
||||
|
||||
NumWorks is a registered trademark of NumWorks SAS, 24 Rue Godot de Mauroy, 75009 Paris, France.
|
||||
Nintendo and Nintendo 3DS are registered trademarks of Nintendo of America Inc, 4600 150th Ave NE, Redmond, WA 98052, USA.
|
||||
NumWorks SAS and Nintendo of America Inc aren't associated in any shape or form with this project.
|
||||
Casio is a registered trademark of Casio Computer Co., Ltd. CORPORATION JAPAN 6-2, Hon-machi 1-chome Shibuya-ku, Tokyo JAPAN 151-8543.
|
||||
NumWorks SAS, Nintendo of America Inc and Casio aren't associated in any shape or form with this project.
|
||||
|
||||
* NumWorks Epsilon is released under a [CC BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
|
||||
* Omega is released under a [CC BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
|
||||
- NumWorks Epsilon is released under a [CC BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
|
||||
- Omega is released under a [CC BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
|
||||
- Upsilon is released under a [CC BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
|
||||
|
||||
@@ -11,6 +11,25 @@ apps =
|
||||
# (path to the apps header).
|
||||
$(foreach i,${apps_list},${eval include apps/$(i)/Makefile})
|
||||
|
||||
app_equals = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1)))
|
||||
# We list all the apps that are missing
|
||||
apps_missing = $(foreach i, ${apps_list}, $(if $(call app_equals, apps/$(i)/Makefile, $(wildcard apps/$(i)/Makefile)),, $(i) ) )
|
||||
|
||||
# If the two doesn't match, we got an error.
|
||||
ifneq ($(strip $(apps_missing)),)
|
||||
miss_modules = 0
|
||||
|
||||
# Check if the missing apps are one that are supposed to be submodules
|
||||
$(foreach i, $(SUBMODULES_APPS), $(if $(call app_equals, $(filter $(i), $(apps_missing)), $(i)), $(eval miss_modules=1)))
|
||||
|
||||
ifeq ($(miss_modules), 1)
|
||||
PLS_IGNORE := $(shell >&2 printf "\nSome submodules apps seem to be missing. To download them, assuming you git clone'd the repo, do\n")
|
||||
PLS_IGNORE := $(shell >&2 printf " git submodule init\n")
|
||||
PLS_IGNORE := $(shell >&2 printf " git submodule update\n\n")
|
||||
endif
|
||||
$(error Missing apps: $(strip $(apps_missing)))
|
||||
endif
|
||||
|
||||
apps_src += $(addprefix apps/,\
|
||||
alternate_empty_nested_menu_controller.cpp \
|
||||
apps_container.cpp \
|
||||
@@ -25,11 +44,13 @@ apps_src += $(addprefix apps/,\
|
||||
backlight_dimming_timer.cpp \
|
||||
battery_timer.cpp \
|
||||
battery_view.cpp \
|
||||
clock_timer.cpp \
|
||||
empty_battery_window.cpp \
|
||||
exam_pop_up_controller.cpp \
|
||||
exam_mode_configuration_official.cpp:+official \
|
||||
exam_mode_configuration_non_official.cpp:-official \
|
||||
global_preferences.cpp \
|
||||
host_filemanager.cpp \
|
||||
i18n.py \
|
||||
lock_view.cpp \
|
||||
main.cpp \
|
||||
@@ -38,10 +59,15 @@ apps_src += $(addprefix apps/,\
|
||||
math_variable_box_empty_controller.cpp \
|
||||
shift_alpha_lock_view.cpp \
|
||||
suspend_timer.cpp \
|
||||
timer_manager.cpp \
|
||||
title_bar_view.cpp \
|
||||
xnt_loop.cpp \
|
||||
)
|
||||
|
||||
tests_src += $(addprefix apps/,\
|
||||
exam_mode_configuration_non_official.cpp \
|
||||
)
|
||||
|
||||
tests_src += apps/exam_mode_configuration_non_official.cpp
|
||||
|
||||
snapshots_declaration = $(foreach i,$(apps),$(i)::Snapshot m_snapshot$(subst :,,$(i))Snapshot;)
|
||||
apps_declaration = $(foreach i,$(apps),$(i) m_$(subst :,,$(i));)
|
||||
@@ -55,23 +81,23 @@ $(call object_for,apps/apps_container_storage.cpp apps/apps_container.cpp apps/m
|
||||
|
||||
# I18n file generation
|
||||
|
||||
# The header is refered to as <apps/i18n.h> so make sure it's findable this way
|
||||
country_preferences = apps/country_preferences.csv
|
||||
language_preferences = apps/language_preferences.csv
|
||||
|
||||
# The header is referred to as <apps/i18n.h> so make sure it's findable this way
|
||||
SFLAGS += -I$(BUILD_DIR)
|
||||
|
||||
i18n_files += $(addprefix apps/language_,$(addsuffix .universal.i18n, $(EPSILON_I18N)))
|
||||
ifeq ($(EPSILON_GETOPT),1)
|
||||
i18n_files += $(addprefix apps/language_,$(addsuffix _iso6391.universal.i18n, $(EPSILON_I18N)))
|
||||
endif
|
||||
|
||||
i18n_files += $(call i18n_with_universal_for,shared)
|
||||
i18n_files += $(call i18n_without_universal_for,toolbox)
|
||||
i18n_files += $(call i18n_with_universal_for,toolbox)
|
||||
i18n_files += $(call i18n_without_universal_for,variables)
|
||||
|
||||
$(eval $(call rule_for, \
|
||||
I18N, \
|
||||
apps/i18n.cpp, \
|
||||
$(i18n_files), \
|
||||
$$(PYTHON) apps/i18n.py --codepoints $(code_points) --header $$(subst .cpp,.h,$$@) --implementation $$@ --locales $$(EPSILON_I18N) --files $$^ --generateISO6391locales $$(EPSILON_GETOPT), \
|
||||
$$(PYTHON) apps/i18n.py --codepoints $(code_points) --countrypreferences $(country_preferences) --languagepreferences $(language_preferences) --header $$(subst .cpp,.h,$$@) --implementation $$@ --locales $$(EPSILON_I18N) --countries $$(EPSILON_COUNTRIES) --files $$^, \
|
||||
global \
|
||||
))
|
||||
|
||||
@@ -84,13 +110,17 @@ $(BUILD_DIR)/apps/i18n.h: $(BUILD_DIR)/apps/i18n.cpp
|
||||
$(eval $(call depends_on_image,apps/title_bar_view.cpp,apps/exam_icon.png))
|
||||
|
||||
$(call object_for,$(apps_src) $(tests_src)): $(BUILD_DIR)/apps/i18n.h
|
||||
$(call object_for,$(apps_src) $(tests_src)): $(BUILD_DIR)/apps/home/apps_layout.h
|
||||
$(call object_for,$(apps_src) $(tests_src)): $(BUILD_DIR)/python/port/genhdr/qstrdefs.generated.h
|
||||
|
||||
apps_tests_src = $(app_calculation_test_src) $(app_code_test_src) $(app_probability_test_src) $(app_regression_test_src) $(app_sequence_test_src) $(app_shared_test_src) $(app_statistics_test_src) $(app_settings_test_src) $(app_solver_test_src)
|
||||
$(call object_for,$(apps_src)): $(BUILD_DIR)/apps/home/apps_layout.h
|
||||
|
||||
apps_tests_src = $(app_calculation_test_src) $(app_code_test_src) $(app_graph_test_src) $(app_probability_test_src) $(app_regression_test_src) $(app_sequence_test_src) $(app_shared_test_src) $(app_statistics_test_src) $(app_settings_test_src) $(app_solver_test_src)
|
||||
|
||||
apps_tests_src += $(addprefix apps/,\
|
||||
alternate_empty_nested_menu_controller.cpp \
|
||||
global_preferences.cpp \
|
||||
dummy_timer_manager.cpp \
|
||||
)
|
||||
|
||||
ifeq ($(THEME_REPO),local)
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <ion/backlight.h>
|
||||
#include <poincare/preferences.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
}
|
||||
@@ -27,14 +29,16 @@ AppsContainer::AppsContainer() :
|
||||
m_globalContext(),
|
||||
m_variableBoxController(),
|
||||
m_examPopUpController(this),
|
||||
m_promptController(k_promptMessages, k_promptColors, k_promptNumberOfMessages),
|
||||
m_promptController(k_promptMessages, k_promptFGColors, k_promptBGColors, k_promptNumberOfMessages),
|
||||
m_batteryTimer(),
|
||||
m_suspendTimer(),
|
||||
m_backlightDimmingTimer(),
|
||||
m_clockTimer(ClockTimer(this)),
|
||||
m_homeSnapshot(),
|
||||
m_onBoardingSnapshot(),
|
||||
m_hardwareTestSnapshot(),
|
||||
m_usbConnectedSnapshot()
|
||||
m_usbConnectedSnapshot(),
|
||||
m_startAppSnapshot()
|
||||
{
|
||||
m_emptyBatteryWindow.setFrame(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height), false);
|
||||
// #if __EMSCRIPTEN__
|
||||
@@ -44,7 +48,7 @@ AppsContainer::AppsContainer() :
|
||||
* poincareCircuitBreaker is run. This means either whitelisting all Epsilon
|
||||
* (which makes bigger files to download and slower execution), or
|
||||
* whitelisting all the symbols (that's a big amount of symbols to find and
|
||||
* quite painy to maintain).
|
||||
* quite paint to maintain).
|
||||
* We just remove the circuit breaker for now.
|
||||
* TODO: Put the Poincare circuit breaker back on epsilon's web emulator */
|
||||
|
||||
@@ -55,11 +59,31 @@ AppsContainer::AppsContainer() :
|
||||
Poincare::Expression::SetCircuitBreaker(AppsContainer::poincareCircuitBreaker);
|
||||
// #endif
|
||||
Ion::Storage::sharedStorage()->setDelegate(this);
|
||||
|
||||
addTimer(&m_batteryTimer);
|
||||
addTimer(&m_suspendTimer);
|
||||
addTimer(&m_backlightDimmingTimer);
|
||||
addTimer(&m_clockTimer);
|
||||
}
|
||||
|
||||
bool AppsContainer::poincareCircuitBreaker() {
|
||||
constexpr uint64_t minimalPressDuration = 20;
|
||||
static uint64_t beginningOfInterruption = 0;
|
||||
Ion::Keyboard::State state = Ion::Keyboard::scan();
|
||||
return state.keyDown(Ion::Keyboard::Key::Back);
|
||||
bool interrupt = state.keyDown(Ion::Keyboard::Key::Back) || state.keyDown(Ion::Keyboard::Key::Home) || state.keyDown(Ion::Keyboard::Key::OnOff);
|
||||
if (!interrupt) {
|
||||
beginningOfInterruption = 0;
|
||||
return false;
|
||||
}
|
||||
if (beginningOfInterruption == 0) {
|
||||
beginningOfInterruption = Ion::Timing::millis();
|
||||
return false;
|
||||
}
|
||||
if (Ion::Timing::millis() - beginningOfInterruption > minimalPressDuration) {
|
||||
beginningOfInterruption = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
App::Snapshot * AppsContainer::hardwareTestAppSnapshot() {
|
||||
@@ -128,8 +152,11 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) {
|
||||
* We do it before switching to USB application to redraw the battery
|
||||
* pictogram. */
|
||||
updateBatteryState();
|
||||
if (switchTo(usbConnectedAppSnapshot())) {
|
||||
Ion::USB::DFU();
|
||||
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
|
||||
// If we are in exam mode, we don't switch to usb connected app
|
||||
didProcessEvent = true;
|
||||
} else if (switchTo(usbConnectedAppSnapshot())) {
|
||||
Ion::USB::DFU(true);
|
||||
// Update LED when exiting DFU mode
|
||||
Ion::LED::updateColorWithPlugAndCharge();
|
||||
bool switched = switchTo(activeSnapshot);
|
||||
@@ -202,43 +229,91 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) {
|
||||
return didProcessEvent || alphaLockWantsRedraw;
|
||||
}
|
||||
|
||||
// List of keys that are used to switch between apps, in order of app to go (eg. 0 : First App, 1 : Second App, 2 : Third App, ...)
|
||||
static constexpr Ion::Events::Event switch_events[] = {
|
||||
Ion::Events::ShiftSeven, Ion::Events::ShiftEight, Ion::Events::ShiftNine,
|
||||
Ion::Events::ShiftFour, Ion::Events::ShiftFive, Ion::Events::ShiftSix,
|
||||
Ion::Events::ShiftOne, Ion::Events::ShiftTwo, Ion::Events::ShiftThree,
|
||||
Ion::Events::ShiftZero, Ion::Events::ShiftDot, Ion::Events::ShiftEE
|
||||
};
|
||||
|
||||
bool AppsContainer::processEvent(Ion::Events::Event event) {
|
||||
// Warning: if the window is dirtied, you need to call window()->redraw()
|
||||
if (event == Ion::Events::USBPlug) {
|
||||
if (Ion::USB::isPlugged()) {
|
||||
// If the exam mode is enabled, we ask to disable it, else, we enable USB
|
||||
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
|
||||
displayExamModePopUp(GlobalPreferences::ExamMode::Off);
|
||||
window()->redraw();
|
||||
} else {
|
||||
Ion::USB::enable();
|
||||
}
|
||||
// Update brightness when USB is plugged
|
||||
Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel());
|
||||
} else {
|
||||
// If the USB isn't plugged in USBPlug event, we disable USB
|
||||
Ion::USB::disable();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// If key home or key back is pressed, we switch to the home app.
|
||||
if (event == Ion::Events::Home || event == Ion::Events::Back) {
|
||||
switchTo(appSnapshotAtIndex(0));
|
||||
return true;
|
||||
}
|
||||
// If shift + Home are pressed, we switch to the first app.
|
||||
if (event == Ion::Events::ShiftHome) {
|
||||
switchTo(appSnapshotAtIndex(1));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Iterate through the switch events to find the one that matches the event, if one match, switch to the app at the index of the switch event.
|
||||
for(int i = 0; i < std::min((int) (sizeof(switch_events) / sizeof(Ion::Events::Event)), APPS_CONTAINER_SNAPSHOT_COUNT); i++) {
|
||||
if (event == switch_events[i]) {
|
||||
m_window.redraw(true);
|
||||
switchTo(appSnapshotAtIndex(i+1));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Add EE shortcut to go to the settings (app number 12)
|
||||
if (event == Ion::Events::EE) {
|
||||
switchTo(appSnapshotAtIndex(12));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Add Shift + Ans shortcut to go to the previous app
|
||||
if (event == Ion::Events::ShiftAns) {
|
||||
switchTo(appSnapshotAtIndex(m_lastAppIndex));
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the event is the OnOff key, we suspend the calculator.
|
||||
if (event == Ion::Events::OnOff) {
|
||||
suspend(true);
|
||||
return true;
|
||||
}
|
||||
// If the event is a brightness event, we update the brightness according to the event.
|
||||
if (event == Ion::Events::BrightnessPlus || event == Ion::Events::BrightnessMinus) {
|
||||
int delta = Ion::Backlight::MaxBrightness/GlobalPreferences::NumberOfBrightnessStates;
|
||||
int direction = (event == Ion::Events::BrightnessPlus) ? Ion::Backlight::NumberOfStepsPerShortcut*delta : -delta*Ion::Backlight::NumberOfStepsPerShortcut;
|
||||
int NumberOfStepsPerShortcut = GlobalPreferences::sharedGlobalPreferences()->brightnessShortcut();
|
||||
int direction = (event == Ion::Events::BrightnessPlus) ? NumberOfStepsPerShortcut*delta : -delta*NumberOfStepsPerShortcut;
|
||||
GlobalPreferences::sharedGlobalPreferences()->setBrightnessLevel(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel()+direction);
|
||||
}
|
||||
// Else, the event was not processed.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AppsContainer::switchTo(App::Snapshot * snapshot) {
|
||||
// Get app index of the snapshot
|
||||
int m_appIndexToSwitch = appIndexFromSnapshot(snapshot);
|
||||
// If the app is home, skip app index saving
|
||||
if (m_appIndexToSwitch != 0) {
|
||||
// Save last app index
|
||||
m_lastAppIndex = m_currentAppIndex;
|
||||
// Save current app index
|
||||
m_currentAppIndex = m_appIndexToSwitch;
|
||||
}
|
||||
if (s_activeApp && snapshot != s_activeApp->snapshot()) {
|
||||
resetShiftAlphaStatus();
|
||||
}
|
||||
@@ -275,7 +350,13 @@ void AppsContainer::run() {
|
||||
/* Normal execution. The exception checkpoint must be created before
|
||||
* switching to the first app, because the first app might create nodes on
|
||||
* the pool. */
|
||||
bool switched = switchTo(initialAppSnapshot());
|
||||
bool switched;
|
||||
if (m_startAppSnapshot != nullptr) {
|
||||
switched = switchTo(m_startAppSnapshot);
|
||||
} else {
|
||||
switched = switchTo(initialAppSnapshot());
|
||||
}
|
||||
|
||||
assert(switched);
|
||||
(void) switched; // Silence compilation warning about unused variable.
|
||||
} else {
|
||||
@@ -285,7 +366,7 @@ void AppsContainer::run() {
|
||||
* destroyed from the pool. To avoid using them before packing the app
|
||||
* (in App::willBecomeInactive for instance), we tidy them early on. */
|
||||
s_activeApp->snapshot()->tidy();
|
||||
/* When an app encoutered an exception due to a full pool, the next time
|
||||
/* When an app encountered an exception due to a full pool, the next time
|
||||
* the user enters the app, the same exception could happen again which
|
||||
* would prevent from reopening the app. To avoid being stuck outside the
|
||||
* app causing the issue, we reset its snapshot when leaving it due to
|
||||
@@ -304,6 +385,10 @@ void AppsContainer::run() {
|
||||
switchTo(nullptr);
|
||||
}
|
||||
|
||||
bool AppsContainer::updateClock() {
|
||||
return m_window.updateClock();
|
||||
}
|
||||
|
||||
bool AppsContainer::updateBatteryState() {
|
||||
bool batteryLevelUpdated = m_window.updateBatteryLevel();
|
||||
bool pluggedStateUpdated = m_window.updatePluggedState();
|
||||
@@ -315,6 +400,8 @@ bool AppsContainer::updateBatteryState() {
|
||||
}
|
||||
|
||||
void AppsContainer::refreshPreferences() {
|
||||
m_suspendTimer.reset(GlobalPreferences::sharedGlobalPreferences()->idleBeforeSuspendSeconds()*1000/Timer::TickDuration);
|
||||
m_backlightDimmingTimer.reset(GlobalPreferences::sharedGlobalPreferences()->idleBeforeDimmingSeconds()*1000/Timer::TickDuration);
|
||||
m_window.refreshPreferences();
|
||||
}
|
||||
|
||||
@@ -336,7 +423,7 @@ void AppsContainer::shutdownDueToLowBattery() {
|
||||
* case. */
|
||||
return;
|
||||
}
|
||||
while (Ion::Battery::level() == Ion::Battery::Charge::EMPTY) {
|
||||
while (Ion::Battery::level() == Ion::Battery::Charge::EMPTY && !Ion::USB::isPlugged()) {
|
||||
Ion::Backlight::setBrightness(0);
|
||||
if (!GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
|
||||
/* Unless the LED is lit up for the exam mode, switch off the LED. IF the
|
||||
@@ -360,7 +447,7 @@ bool AppsContainer::updateAlphaLock() {
|
||||
return m_window.updateAlphaLock();
|
||||
}
|
||||
|
||||
OnBoarding::PopUpController * AppsContainer::promptController() {
|
||||
OnBoarding::PromptController * AppsContainer::promptController() {
|
||||
if (k_promptNumberOfMessages == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -408,15 +495,6 @@ Window * AppsContainer::window() {
|
||||
return &m_window;
|
||||
}
|
||||
|
||||
int AppsContainer::numberOfContainerTimers() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
Timer * AppsContainer::containerTimerAtIndex(int i) {
|
||||
Timer * timers[3] = {&m_batteryTimer, &m_suspendTimer, &m_backlightDimmingTimer};
|
||||
return timers[i];
|
||||
}
|
||||
|
||||
void AppsContainer::resetShiftAlphaStatus() {
|
||||
Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default);
|
||||
updateAlphaLock();
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
#include "global_preferences.h"
|
||||
#include "backlight_dimming_timer.h"
|
||||
#include "shared/global_context.h"
|
||||
#include "on_boarding/pop_up_controller.h"
|
||||
#include "clock_timer.h"
|
||||
#include "on_boarding/prompt_controller.h"
|
||||
#include "xnt_loop.h"
|
||||
|
||||
#include <ion/events.h>
|
||||
|
||||
@@ -27,6 +29,7 @@ public:
|
||||
static bool poincareCircuitBreaker();
|
||||
virtual int numberOfApps() = 0;
|
||||
virtual App::Snapshot * appSnapshotAtIndex(int index) = 0;
|
||||
virtual int appIndexFromSnapshot(App::Snapshot * snapshot) = 0;
|
||||
App::Snapshot * initialAppSnapshot();
|
||||
App::Snapshot * hardwareTestAppSnapshot();
|
||||
App::Snapshot * onBoardingAppSnapshot();
|
||||
@@ -39,13 +42,16 @@ public:
|
||||
bool dispatchEvent(Ion::Events::Event event) override;
|
||||
bool switchTo(App::Snapshot * snapshot) override;
|
||||
void run() override;
|
||||
bool updateClock();
|
||||
bool updateBatteryState();
|
||||
void refreshPreferences();
|
||||
void reloadTitleBarView();
|
||||
void displayExamModePopUp(GlobalPreferences::ExamMode mode);
|
||||
void shutdownDueToLowBattery();
|
||||
void setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus newStatus);
|
||||
OnBoarding::PopUpController * promptController();
|
||||
CodePoint XNT(CodePoint defaultXNT, bool * shouldRemoveLastCharacter) { return m_XNTLoop.XNT(defaultXNT, shouldRemoveLastCharacter); }
|
||||
void resetXNT() { m_XNTLoop.reset(); }
|
||||
OnBoarding::PromptController * promptController();
|
||||
void redrawWindow(bool force = false);
|
||||
void activateExamMode(GlobalPreferences::ExamMode examMode);
|
||||
// Exam pop-up controller delegate
|
||||
@@ -53,33 +59,42 @@ public:
|
||||
// Ion::StorageDelegate
|
||||
void storageDidChangeForRecord(const Ion::Storage::Record record) override;
|
||||
void storageIsFull() override;
|
||||
#ifdef EPSILON_GETOPT
|
||||
void setStartApp(App::Snapshot * snapshot) { m_startAppSnapshot = snapshot; }
|
||||
#endif
|
||||
protected:
|
||||
Home::App::Snapshot * homeAppSnapshot() { return &m_homeSnapshot; }
|
||||
private:
|
||||
Window * window() override;
|
||||
int numberOfContainerTimers() override;
|
||||
Timer * containerTimerAtIndex(int i) override;
|
||||
bool processEvent(Ion::Events::Event event);
|
||||
void resetShiftAlphaStatus();
|
||||
bool updateAlphaLock();
|
||||
|
||||
static I18n::Message k_promptMessages[];
|
||||
static KDColor k_promptColors[];
|
||||
static KDColor k_promptFGColors[];
|
||||
static KDColor k_promptBGColors[];
|
||||
static int k_promptNumberOfMessages;
|
||||
int m_currentAppIndex; // Home isn't included after the second app switching
|
||||
int m_lastAppIndex;
|
||||
AppsWindow m_window;
|
||||
EmptyBatteryWindow m_emptyBatteryWindow;
|
||||
Shared::GlobalContext m_globalContext;
|
||||
MathToolbox m_mathToolbox;
|
||||
MathVariableBoxController m_variableBoxController;
|
||||
ExamPopUpController m_examPopUpController;
|
||||
OnBoarding::PopUpController m_promptController;
|
||||
OnBoarding::PromptController m_promptController;
|
||||
BatteryTimer m_batteryTimer;
|
||||
SuspendTimer m_suspendTimer;
|
||||
BacklightDimmingTimer m_backlightDimmingTimer;
|
||||
ClockTimer m_clockTimer;
|
||||
Home::App::Snapshot m_homeSnapshot;
|
||||
OnBoarding::App::Snapshot m_onBoardingSnapshot;
|
||||
HardwareTest::App::Snapshot m_hardwareTestSnapshot;
|
||||
USB::App::Snapshot m_usbConnectedSnapshot;
|
||||
XNTLoop m_XNTLoop;
|
||||
#ifdef EPSILON_GETOPT
|
||||
App::Snapshot * m_startAppSnapshot;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,7 +10,7 @@ I18n::Message AppsContainer::k_promptMessages[] = {
|
||||
I18n::Message::BetaVersionMessage5,
|
||||
I18n::Message::BetaVersionMessage6};
|
||||
|
||||
KDColor AppsContainer::k_promptColors[] = {
|
||||
KDColor AppsContainer::k_promptFGColors[] = {
|
||||
KDColorBlack,
|
||||
KDColorBlack,
|
||||
KDColorBlack,
|
||||
@@ -20,4 +20,14 @@ KDColor AppsContainer::k_promptColors[] = {
|
||||
KDColorBlack,
|
||||
Palette::AccentText};
|
||||
|
||||
KDColor AppsContainer::k_promptBGColors[] = {
|
||||
KDColorWhite,
|
||||
KDColorWhite,
|
||||
KDColorWhite,
|
||||
KDColorWhite,
|
||||
KDColorWhite,
|
||||
KDColorWhite,
|
||||
KDColorWhite,
|
||||
KDColorWhite};
|
||||
|
||||
int AppsContainer::k_promptNumberOfMessages = 8;
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
I18n::Message AppsContainer::k_promptMessages[] = {};
|
||||
|
||||
KDColor AppsContainer::k_promptColors[] = {};
|
||||
KDColor AppsContainer::k_promptFGColors[] = {};
|
||||
KDColor AppsContainer::k_promptBGColors[] = {};
|
||||
|
||||
int AppsContainer::k_promptNumberOfMessages = 0;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ I18n::Message AppsContainer::k_promptMessages[] = {
|
||||
I18n::Message::UpdateMessage3,
|
||||
I18n::Message::UpdateMessage4};
|
||||
|
||||
KDColor AppsContainer::k_promptColors[] = {
|
||||
KDColor AppsContainer::k_promptFGColors[] = {
|
||||
KDColorBlack,
|
||||
KDColorBlack,
|
||||
KDColorBlack,
|
||||
@@ -16,4 +16,12 @@ KDColor AppsContainer::k_promptColors[] = {
|
||||
KDColorBlack,
|
||||
Palette::AccentText};
|
||||
|
||||
KDColor AppsContainer::k_promptBGColors[] = {
|
||||
KDColorWhite,
|
||||
KDColorWhite,
|
||||
KDColorWhite,
|
||||
KDColorBlack,
|
||||
KDColorWhite,
|
||||
KDColorBlack};
|
||||
|
||||
int AppsContainer::k_promptNumberOfMessages = 6;
|
||||
|
||||
@@ -34,5 +34,25 @@ App::Snapshot * AppsContainerStorage::appSnapshotAtIndex(int index) {
|
||||
};
|
||||
assert(sizeof(snapshots)/sizeof(snapshots[0]) == k_numberOfCommonApps);
|
||||
assert(index >= 0 && index < k_numberOfCommonApps);
|
||||
// To avoid crashes, we return the home app snapshot if the index is out of
|
||||
// bounds. (no crash in release mode, but an assert in debug mode)
|
||||
if (index >= k_numberOfCommonApps) {
|
||||
return snapshots[0];
|
||||
}
|
||||
return snapshots[index];
|
||||
}
|
||||
|
||||
// Get the index of the app from its snapshot
|
||||
int AppsContainerStorage::appIndexFromSnapshot(App::Snapshot * snapshot) {
|
||||
App::Snapshot * snapshots[] = {
|
||||
homeAppSnapshot()
|
||||
APPS_CONTAINER_SNAPSHOT_LIST
|
||||
};
|
||||
assert(sizeof(snapshots)/sizeof(snapshots[0]) == k_numberOfCommonApps);
|
||||
for (int i = 0; i < k_numberOfCommonApps; i++) {
|
||||
if (snapshots[i] == snapshot) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ public:
|
||||
AppsContainerStorage();
|
||||
int numberOfApps() override;
|
||||
App::Snapshot * appSnapshotAtIndex(int index) override;
|
||||
int appIndexFromSnapshot(App::Snapshot * snapshot) override;
|
||||
void * currentAppBuffer() override { return &m_apps; };
|
||||
private:
|
||||
union Apps {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
}
|
||||
#include <ion/rtc.h>
|
||||
|
||||
AppsWindow::AppsWindow() :
|
||||
Window(),
|
||||
@@ -19,6 +20,11 @@ bool AppsWindow::updateBatteryLevel() {
|
||||
return m_titleBarView.setChargeState(Ion::Battery::level());
|
||||
}
|
||||
|
||||
bool AppsWindow::updateClock() {
|
||||
Ion::RTC::DateTime dateTime = Ion::RTC::dateTime();
|
||||
return m_titleBarView.setClock(dateTime.tm_hour, dateTime.tm_min, Ion::RTC::mode() != Ion::RTC::Mode::Disabled);
|
||||
}
|
||||
|
||||
bool AppsWindow::updateIsChargingState() {
|
||||
return m_titleBarView.setIsCharging(Ion::Battery::isCharging());
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ public:
|
||||
AppsWindow();
|
||||
void setTitle(I18n::Message title);
|
||||
bool updateBatteryLevel();
|
||||
bool updateClock();
|
||||
bool updateIsChargingState();
|
||||
bool updatePluggedState();
|
||||
void refreshPreferences();
|
||||
|
||||
Submodule apps/atom deleted from 8f710a9d3f
1
apps/atomic
Submodule
1
apps/atomic
Submodule
Submodule apps/atomic added at 5f7063d447
@@ -1,11 +1,26 @@
|
||||
#include "backlight_dimming_timer.h"
|
||||
#include "global_preferences.h"
|
||||
#include <ion/backlight.h>
|
||||
#include <ion/events.h>
|
||||
#include <apps/apps_container.h>
|
||||
|
||||
BacklightDimmingTimer::BacklightDimmingTimer() :
|
||||
Timer(k_idleBeforeDimmingDuration/Timer::TickDuration)
|
||||
Timer(GlobalPreferences::sharedGlobalPreferences()->idleBeforeDimmingSeconds()*1000/Timer::TickDuration)
|
||||
{
|
||||
}
|
||||
|
||||
bool BacklightDimmingTimer::fire() {
|
||||
Ion::Backlight::setBrightness(k_dimBacklightBrightness);
|
||||
bool BacklightDimmingTimer::fire(){
|
||||
int i = Ion::Backlight::brightness();
|
||||
while (i > 0){
|
||||
int t = 20;
|
||||
Ion::Events::Event e = Ion::Events::getEvent(&t);
|
||||
AppsContainer::sharedAppsContainer()->dispatchEvent(e);
|
||||
if (e.isKeyboardEvent()){
|
||||
return false;
|
||||
}
|
||||
|
||||
Ion::Backlight::setBrightness(i);
|
||||
i -= 15;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ class BacklightDimmingTimer : public Timer {
|
||||
public:
|
||||
BacklightDimmingTimer();
|
||||
private:
|
||||
constexpr static int k_idleBeforeDimmingDuration = 30*1000; // In miliseconds
|
||||
constexpr static int k_dimBacklightBrightness = 0;
|
||||
bool fire() override;
|
||||
};
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ BatteryTimer::BatteryTimer() :
|
||||
bool BatteryTimer::fire() {
|
||||
AppsContainer * container = AppsContainer::sharedAppsContainer();
|
||||
bool needRedrawing = container->updateBatteryState();
|
||||
if (Ion::Battery::level() == Ion::Battery::Charge::EMPTY) {
|
||||
if (Ion::Battery::level() == Ion::Battery::Charge::EMPTY && !Ion::USB::isPlugged()) {
|
||||
container->shutdownDueToLowBattery();
|
||||
}
|
||||
return needRedrawing;
|
||||
|
||||
@@ -60,32 +60,36 @@ void BatteryView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
*'content' depends on the charge */
|
||||
|
||||
// Draw the left part
|
||||
ctx->fillRect(KDRect(0, 0, k_elementWidth, k_batteryHeight), Palette::Battery);
|
||||
ctx->fillRect(KDRect(0, 1, k_elementWidth, k_batteryHeight - 2), Palette::Battery);
|
||||
|
||||
// Draw top and bottom part
|
||||
ctx->fillRect(KDRect(1, 0, k_batteryWidth-3, 1), Palette::Battery);
|
||||
ctx->fillRect(KDRect(1, k_batteryHeight-1, k_batteryWidth-3, 1), Palette::Battery);
|
||||
|
||||
// Draw the middle part
|
||||
constexpr KDCoordinate batteryInsideX = k_elementWidth+k_separatorThickness;
|
||||
constexpr KDCoordinate batteryInsideWidth = k_batteryWidth-3*k_elementWidth-2*k_separatorThickness;
|
||||
if (m_isCharging) {
|
||||
// Charging: Yellow background with flash
|
||||
ctx->fillRect(KDRect(batteryInsideX, 0, batteryInsideWidth, k_batteryHeight), Palette::BatteryInCharge);
|
||||
ctx->fillRect(KDRect(batteryInsideX, 2, batteryInsideWidth, k_batteryHeight-4), Palette::BatteryInCharge);
|
||||
KDRect frame((k_batteryWidth-k_flashWidth)/2, 0, k_flashWidth, k_flashHeight);
|
||||
KDColor flashWorkingBuffer[BatteryView::k_flashHeight*BatteryView::k_flashWidth];
|
||||
ctx->blendRectWithMask(frame, Palette::Battery, (const uint8_t *)flashMask, flashWorkingBuffer);
|
||||
} else if (m_chargeState == Ion::Battery::Charge::LOW) {
|
||||
assert(!m_isPlugged);
|
||||
// Low: Quite empty battery
|
||||
ctx->fillRect(KDRect(batteryInsideX, 0, 2*k_elementWidth, k_batteryHeight), Palette::BatteryLow);
|
||||
ctx->fillRect(KDRect(3*k_elementWidth+k_separatorThickness, 0, k_batteryWidth-5*k_elementWidth-2*k_separatorThickness, k_batteryHeight), Palette::BatteryInCharge);
|
||||
ctx->fillRect(KDRect(batteryInsideX, 2, 2*k_elementWidth, k_batteryHeight-4), Palette::BatteryLow);
|
||||
ctx->fillRect(KDRect(3*k_elementWidth+k_separatorThickness, 2, k_batteryWidth-5*k_elementWidth-2*k_separatorThickness, k_batteryHeight-4), KDColor::blend(Palette::Toolbar, Palette::Battery, 128));
|
||||
} else if (m_chargeState == Ion::Battery::Charge::SOMEWHERE_INBETWEEN) {
|
||||
assert(!m_isPlugged);
|
||||
// Middle: Half full battery
|
||||
constexpr KDCoordinate middleChargeWidth = batteryInsideWidth/2;
|
||||
ctx->fillRect(KDRect(batteryInsideX, 0, middleChargeWidth, k_batteryHeight), Palette::Battery);
|
||||
ctx->fillRect(KDRect(batteryInsideX+middleChargeWidth, 0, middleChargeWidth, k_batteryHeight), Palette::BatteryInCharge);
|
||||
ctx->fillRect(KDRect(batteryInsideX, 2, middleChargeWidth, k_batteryHeight-4), Palette::Battery);
|
||||
ctx->fillRect(KDRect(batteryInsideX+middleChargeWidth, 2, middleChargeWidth+1, k_batteryHeight-4), KDColor::blend(Palette::Toolbar, Palette::Battery, 128));
|
||||
} else {
|
||||
assert(m_chargeState == Ion::Battery::Charge::FULL);
|
||||
// Full but not plugged: Full battery
|
||||
ctx->fillRect(KDRect(batteryInsideX, 0, batteryInsideWidth, k_batteryHeight), Palette::Battery);
|
||||
ctx->fillRect(KDRect(batteryInsideX, 2, batteryInsideWidth, k_batteryHeight-4), Palette::Battery);
|
||||
if (m_isPlugged) {
|
||||
// Plugged and full: Full battery with tick
|
||||
KDRect frame((k_batteryWidth-k_tickWidth)/2, (k_batteryHeight-k_tickHeight)/2, k_tickWidth, k_tickHeight);
|
||||
@@ -95,7 +99,7 @@ void BatteryView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
}
|
||||
|
||||
// Draw the right part
|
||||
ctx->fillRect(KDRect(k_batteryWidth-2*k_elementWidth, 0, k_elementWidth, k_batteryHeight), Palette::Battery);
|
||||
ctx->fillRect(KDRect(k_batteryWidth-2*k_elementWidth, 1, k_elementWidth, k_batteryHeight-2), Palette::Battery);
|
||||
ctx->fillRect(KDRect(k_batteryWidth-k_elementWidth, (k_batteryHeight-k_capHeight)/2, k_elementWidth, k_capHeight), Palette::Battery);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@ public:
|
||||
constexpr static int k_tickHeight = 6;
|
||||
constexpr static int k_tickWidth = 8;
|
||||
private:
|
||||
constexpr static KDCoordinate k_batteryHeight = 8;
|
||||
constexpr static KDCoordinate k_batteryWidth = 15;
|
||||
constexpr static KDCoordinate k_batteryHeight = 9;
|
||||
constexpr static KDCoordinate k_batteryWidth = 16;
|
||||
constexpr static KDCoordinate k_elementWidth = 1;
|
||||
constexpr static KDCoordinate k_capHeight = 4;
|
||||
constexpr static KDCoordinate k_capHeight = 3;
|
||||
constexpr static KDCoordinate k_separatorThickness = Metric::CellSeparatorThickness;
|
||||
Ion::Battery::Charge m_chargeState;
|
||||
bool m_isCharging;
|
||||
|
||||
@@ -17,7 +17,9 @@ app_calculation_src = $(addprefix apps/calculation/,\
|
||||
additional_outputs/integer_list_controller.cpp \
|
||||
additional_outputs/scrollable_three_expressions_cell.cpp \
|
||||
additional_outputs/list_controller.cpp \
|
||||
additional_outputs/matrix_list_controller.cpp \
|
||||
additional_outputs/rational_list_controller.cpp \
|
||||
additional_outputs/second_degree_list_controller.cpp \
|
||||
additional_outputs/trigonometry_graph_cell.cpp \
|
||||
additional_outputs/trigonometry_list_controller.cpp \
|
||||
additional_outputs/trigonometry_model.cpp \
|
||||
|
||||
@@ -11,7 +11,7 @@ ExpressionsListController::ExpressionsListController(EditExpressionController *
|
||||
ListController(editExpressionController),
|
||||
m_cells{}
|
||||
{
|
||||
for (int i = 0; i < k_maxNumberOfCells; i++) {
|
||||
for (int i = 0; i < k_maxNumberOfRows; i++) {
|
||||
m_cells[i].setParentResponder(m_listController.selectableTableView());
|
||||
}
|
||||
}
|
||||
@@ -21,15 +21,20 @@ void ExpressionsListController::didEnterResponderChain(Responder * previousFirst
|
||||
}
|
||||
|
||||
int ExpressionsListController::reusableCellCount(int type) {
|
||||
return k_maxNumberOfCells;
|
||||
return k_maxNumberOfRows;
|
||||
}
|
||||
|
||||
void ExpressionsListController::viewDidDisappear() {
|
||||
ListController::viewDidDisappear();
|
||||
// Reset cell memoization to avoid taking extra space in the pool
|
||||
for (int i = 0; i < k_maxNumberOfCells; i++) {
|
||||
// Reset layout and cell memoization to avoid taking extra space in the pool
|
||||
for (int i = 0; i < k_maxNumberOfRows; i++) {
|
||||
m_cells[i].setLayout(Layout());
|
||||
/* By reseting m_layouts, numberOfRow will go down to 0, and the highlighted
|
||||
* cells won't be unselected. Therefore we unselect them here. */
|
||||
m_cells[i].setHighlighted(false);
|
||||
m_layouts[i] = Layout();
|
||||
}
|
||||
m_expression = Expression();
|
||||
}
|
||||
|
||||
HighlightCell * ExpressionsListController::reusableCell(int index, int type) {
|
||||
@@ -43,24 +48,34 @@ KDCoordinate ExpressionsListController::rowHeight(int j) {
|
||||
}
|
||||
|
||||
void ExpressionsListController::willDisplayCellForIndex(HighlightCell * cell, int index) {
|
||||
/* Note : To further optimize memoization space in the pool, layout
|
||||
* serialization could be memoized instead, and layout would be recomputed
|
||||
* here, when setting cell's layout. */
|
||||
ExpressionTableCellWithPointer * myCell = static_cast<ExpressionTableCellWithPointer *>(cell);
|
||||
myCell->setLayout(layoutAtIndex(index));
|
||||
myCell->setAccessoryMessage(messageAtIndex(index));
|
||||
myCell->reloadScroll();
|
||||
}
|
||||
|
||||
int ExpressionsListController::numberOfRows() const {
|
||||
int nbOfRows = 0;
|
||||
for (size_t i = 0; i < k_maxNumberOfRows; i++) {
|
||||
if (!m_layouts[i].isUninitialized()) {
|
||||
nbOfRows++;
|
||||
}
|
||||
}
|
||||
return nbOfRows;
|
||||
}
|
||||
|
||||
void ExpressionsListController::setExpression(Poincare::Expression e) {
|
||||
// Reinitialize memoization
|
||||
for (int i = 0; i < k_maxNumberOfCells; i++) {
|
||||
for (int i = 0; i < k_maxNumberOfRows; i++) {
|
||||
m_layouts[i] = Layout();
|
||||
}
|
||||
m_expression = e;
|
||||
}
|
||||
|
||||
Poincare::Layout ExpressionsListController::layoutAtIndex(int index) {
|
||||
if (m_layouts[index].isUninitialized()) {
|
||||
computeLayoutAtIndex(index);
|
||||
}
|
||||
assert(!m_layouts[index].isUninitialized());
|
||||
return m_layouts[index];
|
||||
}
|
||||
|
||||
@@ -22,22 +22,22 @@ public:
|
||||
KDCoordinate rowHeight(int j) override;
|
||||
int typeAtLocation(int i, int j) override { return 0; }
|
||||
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
|
||||
int numberOfRows() const override;
|
||||
|
||||
// IllustratedListController
|
||||
void setExpression(Poincare::Expression e) override;
|
||||
|
||||
protected:
|
||||
constexpr static int k_maxNumberOfCells = 4;
|
||||
constexpr static int k_maxNumberOfRows = 5;
|
||||
int textAtIndex(char * buffer, size_t bufferSize, int index) override;
|
||||
Poincare::Expression m_expression;
|
||||
// Memoization of layouts
|
||||
mutable Poincare::Layout m_layouts[k_maxNumberOfCells];
|
||||
mutable Poincare::Layout m_layouts[k_maxNumberOfRows];
|
||||
private:
|
||||
Poincare::Layout layoutAtIndex(int index);
|
||||
virtual void computeLayoutAtIndex(int index) = 0;
|
||||
virtual I18n::Message messageAtIndex(int index) = 0;
|
||||
// Cells
|
||||
ExpressionTableCellWithPointer m_cells[k_maxNumberOfCells];
|
||||
ExpressionTableCellWithPointer m_cells[k_maxNumberOfRows];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace Calculation {
|
||||
|
||||
IllustratedListController::IllustratedListController(EditExpressionController * editExpressionController) :
|
||||
ListController(editExpressionController, this),
|
||||
m_calculationStore(m_calculationStoreBuffer, k_calculationStoreBufferSize),
|
||||
m_additionalCalculationCells{}
|
||||
{
|
||||
for (int i = 0; i < k_maxNumberOfAdditionalCalculations; i++) {
|
||||
|
||||
@@ -39,7 +39,10 @@ protected:
|
||||
private:
|
||||
int textAtIndex(char * buffer, size_t bufferSize, int index) override;
|
||||
virtual CodePoint expressionSymbol() const = 0;
|
||||
// Set the size of the buffer needed to store the additional calculation
|
||||
constexpr static int k_maxNumberOfAdditionalCalculations = 4;
|
||||
constexpr static int k_calculationStoreBufferSize = k_maxNumberOfAdditionalCalculations * (sizeof(Calculation) + Calculation::k_numberOfExpressions * Constant::MaxSerializedExpressionSize + sizeof(Calculation *));
|
||||
char m_calculationStoreBuffer[k_calculationStoreBufferSize];
|
||||
// Cells
|
||||
virtual HighlightCell * illustrationCell() = 0;
|
||||
ScrollableThreeExpressionsCell m_additionalCalculationCells[k_maxNumberOfAdditionalCalculations];
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "integer_list_controller.h"
|
||||
#include <poincare/based_integer.h>
|
||||
#include <poincare/opposite.h>
|
||||
#include <poincare/integer.h>
|
||||
#include <poincare/logarithm.h>
|
||||
#include <poincare/empty_layout.h>
|
||||
#include <poincare/factor.h>
|
||||
#include "../app.h"
|
||||
@@ -11,10 +13,6 @@ using namespace Shared;
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
int IntegerListController::numberOfRows() const {
|
||||
return 3 + factorExpressionIsComputable();
|
||||
}
|
||||
|
||||
Integer::Base baseAtIndex(int index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
@@ -27,12 +25,40 @@ Integer::Base baseAtIndex(int index) {
|
||||
}
|
||||
}
|
||||
|
||||
void IntegerListController::computeLayoutAtIndex(int index) {
|
||||
assert(m_expression.type() == ExpressionNode::Type::BasedInteger);
|
||||
// For index = k_indexOfFactorExpression, the layout is assumed to be alreday memoized because it is needed to compute the numberOfRows
|
||||
assert(index < k_indexOfFactorExpression);
|
||||
Integer i = static_cast<BasedInteger &>(m_expression).integer();
|
||||
m_layouts[index] = i.createLayout(baseAtIndex(index));
|
||||
void IntegerListController::setExpression(Poincare::Expression e) {
|
||||
ExpressionsListController::setExpression(e);
|
||||
static_assert(k_maxNumberOfRows >= k_indexOfFactorExpression + 1, "k_maxNumberOfRows must be greater than k_indexOfFactorExpression");
|
||||
assert(!m_expression.isUninitialized() && m_expression.type() == ExpressionNode::Type::BasedInteger || (m_expression.type() == ExpressionNode::Type::Opposite && m_expression.childAtIndex(0).type() == ExpressionNode::Type::BasedInteger));
|
||||
assert(!m_expression.isUninitialized());
|
||||
|
||||
if (m_expression.type() == ExpressionNode::Type::BasedInteger) {
|
||||
Integer integer = static_cast<BasedInteger &>(m_expression).integer();
|
||||
for (int index = 0; index < k_indexOfFactorExpression; ++index) {
|
||||
m_layouts[index] = integer.createLayout(baseAtIndex(index));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Opposite b = static_cast<Opposite &>(m_expression);
|
||||
Expression e = b.childAtIndex(0);
|
||||
Integer childInt = static_cast<BasedInteger &>(e).integer();
|
||||
childInt.setNegative(true);
|
||||
Integer num_bits = Integer::CeilingLog2(childInt);
|
||||
Integer integer = Integer::TwosComplementToBits(childInt, num_bits);
|
||||
for (int index = 0; index < k_indexOfFactorExpression; ++index) {
|
||||
if(baseAtIndex(index) == Integer::Base::Decimal) {
|
||||
m_layouts[index] = childInt.createLayout(baseAtIndex(index));
|
||||
} else {
|
||||
m_layouts[index] = integer.createLayout(baseAtIndex(index));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Computing factorExpression
|
||||
Expression factor = Factor::Builder(m_expression.clone());
|
||||
PoincareHelpers::Simplify(&factor, App::app()->localContext(), ExpressionNode::ReductionTarget::User);
|
||||
if (!factor.isUndefined()) {
|
||||
m_layouts[k_indexOfFactorExpression] = PoincareHelpers::CreateLayout(factor);
|
||||
}
|
||||
}
|
||||
|
||||
I18n::Message IntegerListController::messageAtIndex(int index) {
|
||||
@@ -48,20 +74,4 @@ I18n::Message IntegerListController::messageAtIndex(int index) {
|
||||
}
|
||||
}
|
||||
|
||||
bool IntegerListController::factorExpressionIsComputable() const {
|
||||
if (!m_layouts[k_indexOfFactorExpression].isUninitialized()) {
|
||||
// The factor expression is already memoized
|
||||
return !m_layouts[k_indexOfFactorExpression].isEmpty();
|
||||
}
|
||||
Poincare::Context * context = App::app()->localContext();
|
||||
Expression factor = Factor::Builder(m_expression.clone());
|
||||
PoincareHelpers::Simplify(&factor, context, ExpressionNode::ReductionTarget::User);
|
||||
if (!factor.isUndefined()) {
|
||||
m_layouts[k_indexOfFactorExpression] = PoincareHelpers::CreateLayout(factor);
|
||||
return true;
|
||||
}
|
||||
m_layouts[k_indexOfFactorExpression] = EmptyLayout::Builder();
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,13 +10,11 @@ public:
|
||||
IntegerListController(EditExpressionController * editExpressionController) :
|
||||
ExpressionsListController(editExpressionController) {}
|
||||
|
||||
//ListViewDataSource
|
||||
int numberOfRows() const override;
|
||||
void setExpression(Poincare::Expression e) override;
|
||||
|
||||
private:
|
||||
static constexpr int k_indexOfFactorExpression = 3;
|
||||
void computeLayoutAtIndex(int index) override;
|
||||
I18n::Message messageAtIndex(int index) override;
|
||||
bool factorExpressionIsComputable() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
106
apps/calculation/additional_outputs/matrix_list_controller.cpp
Normal file
106
apps/calculation/additional_outputs/matrix_list_controller.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
#include "matrix_list_controller.h"
|
||||
#include "../app.h"
|
||||
#include "../../shared/poincare_helpers.h"
|
||||
#include <apps/global_preferences.h>
|
||||
#include <poincare_nodes.h>
|
||||
#include <poincare/matrix.h>
|
||||
#include <string.h>
|
||||
|
||||
using namespace Poincare;
|
||||
using namespace Shared;
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
void MatrixListController::setExpression(Poincare::Expression e) {
|
||||
ExpressionsListController::setExpression(e);
|
||||
assert(!m_expression.isUninitialized());
|
||||
static_assert(k_maxNumberOfRows >= k_maxNumberOfOutputRows, "k_maxNumberOfRows must be greater than k_maxNumberOfOutputRows");
|
||||
|
||||
Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences();
|
||||
Poincare::Preferences::ComplexFormat currentComplexFormat = preferences->complexFormat();
|
||||
if (currentComplexFormat == Poincare::Preferences::ComplexFormat::Real) {
|
||||
/* Temporary change complex format to avoid all additional expressions to be
|
||||
* "unreal" (with [i] for instance). As additional results are computed from
|
||||
* the output, which is built taking ComplexFormat into account, there are
|
||||
* no risks of displaying additional results on an unreal output. */
|
||||
preferences->setComplexFormat(Poincare::Preferences::ComplexFormat::Cartesian);
|
||||
}
|
||||
|
||||
Context * context = App::app()->localContext();
|
||||
ExpressionNode::ReductionContext reductionContext(
|
||||
context,
|
||||
preferences->complexFormat(),
|
||||
preferences->angleUnit(),
|
||||
GlobalPreferences::sharedGlobalPreferences()->unitFormat(),
|
||||
ExpressionNode::ReductionTarget::SystemForApproximation,
|
||||
ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined);
|
||||
|
||||
// The expression must be reduced to call methods such as determinant or trace
|
||||
assert(m_expression.type() == ExpressionNode::Type::Matrix);
|
||||
|
||||
bool mIsSquared = (static_cast<Matrix &>(m_expression).numberOfRows() == static_cast<Matrix &>(m_expression).numberOfColumns());
|
||||
size_t index = 0;
|
||||
size_t messageIndex = 0;
|
||||
// 1. Matrix determinant if square matrix
|
||||
if (mIsSquared) {
|
||||
/* Determinant is reduced so that a null determinant can be detected.
|
||||
* However, some exceptions remain such as cos(x)^2+sin(x)^2-1 which will
|
||||
* not be reduced to a rational, but will be null in theory. */
|
||||
Expression determinant = Determinant::Builder(m_expression.clone()).reduce(reductionContext);
|
||||
m_indexMessageMap[index] = messageIndex++;
|
||||
m_layouts[index++] = getLayoutFromExpression(determinant, context, preferences);
|
||||
// 2. Matrix inverse if invertible matrix
|
||||
// A squared matrix is invertible if and only if determinant is non null
|
||||
if (!determinant.isUndefined() && determinant.nullStatus(context) != ExpressionNode::NullStatus::Null) {
|
||||
// TODO: Handle ExpressionNode::NullStatus::Unknown
|
||||
m_indexMessageMap[index] = messageIndex++;
|
||||
m_layouts[index++] = getLayoutFromExpression(MatrixInverse::Builder(m_expression.clone()), context, preferences);
|
||||
}
|
||||
}
|
||||
// 3. Matrix row echelon form
|
||||
messageIndex = 2;
|
||||
Expression rowEchelonForm = MatrixRowEchelonForm::Builder(m_expression.clone());
|
||||
m_indexMessageMap[index] = messageIndex++;
|
||||
m_layouts[index++] = getLayoutFromExpression(rowEchelonForm, context, preferences);
|
||||
/* 4. Matrix reduced row echelon form
|
||||
* it can be computed from row echelon form to save computation time.*/
|
||||
m_indexMessageMap[index] = messageIndex++;
|
||||
m_layouts[index++] = getLayoutFromExpression(MatrixReducedRowEchelonForm::Builder(rowEchelonForm), context, preferences);
|
||||
// 5. Matrix trace if square matrix
|
||||
if (mIsSquared) {
|
||||
m_indexMessageMap[index] = messageIndex++;
|
||||
m_layouts[index++] = getLayoutFromExpression(MatrixTrace::Builder(m_expression.clone()), context, preferences);
|
||||
}
|
||||
// Reset complex format as before
|
||||
preferences->setComplexFormat(currentComplexFormat);
|
||||
}
|
||||
|
||||
Poincare::Layout MatrixListController::getLayoutFromExpression(Expression e, Context * context, Poincare::Preferences * preferences) {
|
||||
assert(!e.isUninitialized());
|
||||
// Simplify or approximate expression
|
||||
Expression approximateExpression;
|
||||
Expression simplifiedExpression;
|
||||
e.simplifyAndApproximate(&simplifiedExpression, &approximateExpression, context,
|
||||
preferences->complexFormat(), preferences->angleUnit(), GlobalPreferences::sharedGlobalPreferences()->unitFormat(),
|
||||
ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined);
|
||||
// simplify might have been interrupted, in which case we use approximate
|
||||
if (simplifiedExpression.isUninitialized()) {
|
||||
assert(!approximateExpression.isUninitialized());
|
||||
return Shared::PoincareHelpers::CreateLayout(approximateExpression);
|
||||
}
|
||||
return Shared::PoincareHelpers::CreateLayout(simplifiedExpression);
|
||||
}
|
||||
|
||||
I18n::Message MatrixListController::messageAtIndex(int index) {
|
||||
// Message index is mapped in setExpression because it depends on the Matrix.
|
||||
assert(index < k_maxNumberOfOutputRows && index >=0);
|
||||
I18n::Message messages[k_maxNumberOfOutputRows] = {
|
||||
I18n::Message::AdditionalDeterminant,
|
||||
I18n::Message::AdditionalInverse,
|
||||
I18n::Message::AdditionalRowEchelonForm,
|
||||
I18n::Message::AdditionalReducedRowEchelonForm,
|
||||
I18n::Message::AdditionalTrace};
|
||||
return messages[m_indexMessageMap[index]];
|
||||
}
|
||||
|
||||
}
|
||||
27
apps/calculation/additional_outputs/matrix_list_controller.h
Normal file
27
apps/calculation/additional_outputs/matrix_list_controller.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef CALCULATION_ADDITIONAL_OUTPUTS_MATRIX_LIST_CONTROLLER_H
|
||||
#define CALCULATION_ADDITIONAL_OUTPUTS_MATRIX_LIST_CONTROLLER_H
|
||||
|
||||
#include "expressions_list_controller.h"
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
class MatrixListController : public ExpressionsListController {
|
||||
public:
|
||||
MatrixListController(EditExpressionController * editExpressionController) :
|
||||
ExpressionsListController(editExpressionController) {}
|
||||
|
||||
void setExpression(Poincare::Expression e) override;
|
||||
|
||||
private:
|
||||
I18n::Message messageAtIndex(int index) override;
|
||||
Poincare::Layout getLayoutFromExpression(Poincare::Expression e, Poincare::Context * context, Poincare::Preferences * preferences);
|
||||
// Map from cell index to message index
|
||||
constexpr static int k_maxNumberOfOutputRows = 5;
|
||||
int m_indexMessageMap[k_maxNumberOfOutputRows];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -9,34 +9,31 @@ using namespace Shared;
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
int RationalListController::numberOfRows() const {
|
||||
return 2;
|
||||
}
|
||||
|
||||
Integer extractInteger(const Expression e) {
|
||||
assert(e.type() == ExpressionNode::Type::BasedInteger);
|
||||
return static_cast<const BasedInteger &>(e).integer();
|
||||
}
|
||||
|
||||
void RationalListController::computeLayoutAtIndex(int index) {
|
||||
void RationalListController::setExpression(Poincare::Expression e) {
|
||||
ExpressionsListController::setExpression(e);
|
||||
assert(!m_expression.isUninitialized());
|
||||
static_assert(k_maxNumberOfRows >= 2, "k_maxNumberOfRows must be greater than 2");
|
||||
|
||||
bool negative = false;
|
||||
Expression div = m_expression;
|
||||
if (m_expression.type() == ExpressionNode::Type::Opposite) {
|
||||
negative = true;
|
||||
div = m_expression.childAtIndex(0);
|
||||
}
|
||||
|
||||
assert(div.type() == ExpressionNode::Type::Division);
|
||||
Integer numerator = extractInteger(div.childAtIndex(0));
|
||||
numerator.setNegative(negative);
|
||||
Integer denominator = extractInteger(div.childAtIndex(1));
|
||||
Expression e;
|
||||
if (index == 0) {
|
||||
e = Integer::CreateMixedFraction(numerator, denominator);
|
||||
} else {
|
||||
assert(index == 1);
|
||||
e = Integer::CreateEuclideanDivision(numerator, denominator);
|
||||
}
|
||||
m_layouts[index] = PoincareHelpers::CreateLayout(e);
|
||||
|
||||
int index = 0;
|
||||
m_layouts[index++] = PoincareHelpers::CreateLayout(Integer::CreateMixedFraction(numerator, denominator));
|
||||
m_layouts[index++] = PoincareHelpers::CreateLayout(Integer::CreateEuclideanDivision(numerator, denominator));
|
||||
}
|
||||
|
||||
I18n::Message RationalListController::messageAtIndex(int index) {
|
||||
|
||||
@@ -10,10 +10,9 @@ public:
|
||||
RationalListController(EditExpressionController * editExpressionController) :
|
||||
ExpressionsListController(editExpressionController) {}
|
||||
|
||||
//ListViewDataSource
|
||||
int numberOfRows() const override;
|
||||
void setExpression(Poincare::Expression e) override;
|
||||
|
||||
private:
|
||||
void computeLayoutAtIndex(int index) override;
|
||||
I18n::Message messageAtIndex(int index) override;
|
||||
int textAtIndex(char * buffer, size_t bufferSize, int index) override;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,320 @@
|
||||
#include "../app.h"
|
||||
#include <apps/global_preferences.h>
|
||||
#include "../../shared/poincare_helpers.h"
|
||||
#include <poincare/layout_helper.h>
|
||||
#include <poincare/code_point_layout.h>
|
||||
#include <poincare/rational.h>
|
||||
#include <poincare/opposite.h>
|
||||
#include <poincare/addition.h>
|
||||
#include <poincare/parenthesis.h>
|
||||
#include <poincare/equal.h>
|
||||
#include <poincare/subtraction.h>
|
||||
#include <poincare/multiplication.h>
|
||||
#include <poincare/division.h>
|
||||
#include <poincare/square_root.h>
|
||||
#include <poincare/symbol.h>
|
||||
#include <poincare/power.h>
|
||||
#include "second_degree_list_controller.h"
|
||||
|
||||
using namespace Poincare;
|
||||
using namespace Shared;
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
void SecondDegreeListController::setExpression(Poincare::Expression e) {
|
||||
ExpressionsListController::setExpression(e);
|
||||
assert(!m_expression.isUninitialized());
|
||||
|
||||
Expression polynomialCoefficients[Expression::k_maxNumberOfPolynomialCoefficients];
|
||||
|
||||
Context * context = App::app()->localContext();
|
||||
Preferences * preferences = Preferences::sharedPreferences();
|
||||
Poincare::ExpressionNode::ReductionContext reductionContext = Poincare::ExpressionNode::ReductionContext(context,
|
||||
preferences->complexFormat(), preferences->angleUnit(),
|
||||
GlobalPreferences::sharedGlobalPreferences()->unitFormat(),
|
||||
ExpressionNode::ReductionTarget::SystemForApproximation,
|
||||
ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition,
|
||||
Poincare::ExpressionNode::UnitConversion::Default);
|
||||
|
||||
PoincareHelpers::Reduce(&m_expression, context, ExpressionNode::ReductionTarget::SystemForAnalysis);
|
||||
|
||||
int degree = m_expression.getPolynomialReducedCoefficients(
|
||||
"x",
|
||||
polynomialCoefficients,
|
||||
context,
|
||||
Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), m_expression, context),
|
||||
preferences->angleUnit(),
|
||||
GlobalPreferences::sharedGlobalPreferences()->unitFormat(),
|
||||
ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition);
|
||||
|
||||
assert(degree == 2);
|
||||
|
||||
Expression a = polynomialCoefficients[2];
|
||||
Expression b = polynomialCoefficients[1];
|
||||
Expression c = polynomialCoefficients[0];
|
||||
|
||||
Expression delta = Subtraction::Builder(Power::Builder(b.clone(), Rational::Builder(2)), Multiplication::Builder(Rational::Builder(4), a.clone(), c.clone()));
|
||||
PoincareHelpers::Simplify(&delta, context, ExpressionNode::ReductionTarget::SystemForApproximation);
|
||||
|
||||
// Alpha is -b/2a, but because after we use -α, we immediately store -α=-(-b/2a)=b/2a.
|
||||
Expression minusAlpha = Division::Builder(b.clone(), Multiplication::Builder(Rational::Builder(2), a.clone()));
|
||||
PoincareHelpers::Reduce(&minusAlpha, context, ExpressionNode::ReductionTarget::SystemForApproximation);
|
||||
|
||||
// Same thing for β
|
||||
Expression minusBeta = Division::Builder(delta.clone(), Multiplication::Builder(Rational::Builder(4), a.clone()));
|
||||
PoincareHelpers::Reduce(&minusBeta, context, ExpressionNode::ReductionTarget::SystemForApproximation);
|
||||
|
||||
enum MultiplicationTypeForA {
|
||||
Nothing,
|
||||
Minus,
|
||||
Parenthesis,
|
||||
Normal
|
||||
};
|
||||
|
||||
MultiplicationTypeForA multiplicationTypeForA;
|
||||
|
||||
if (a.type() == ExpressionNode::Type::Rational && static_cast<const Rational &>(a).isOne()) {
|
||||
multiplicationTypeForA = MultiplicationTypeForA::Nothing;
|
||||
} else if(a.type() == ExpressionNode::Type::Rational && static_cast<const Rational &>(a).isMinusOne()){
|
||||
multiplicationTypeForA = MultiplicationTypeForA::Minus;
|
||||
} else if (a.type() == ExpressionNode::Type::Addition) {
|
||||
multiplicationTypeForA = MultiplicationTypeForA::Parenthesis;
|
||||
} else {
|
||||
multiplicationTypeForA = MultiplicationTypeForA::Normal;
|
||||
}
|
||||
|
||||
PoincareHelpers::Simplify(&a, context, ExpressionNode::ReductionTarget::User);
|
||||
|
||||
/*
|
||||
* Because when can't apply reduce or simplify to keep the
|
||||
* canonized form we must beautify the expression manually
|
||||
*/
|
||||
|
||||
Expression xMinusAlphaPowerTwo;
|
||||
Expression alpha = getOppositeIfExists(minusAlpha, &reductionContext);
|
||||
|
||||
if (alpha.isUninitialized()) {
|
||||
PoincareHelpers::Simplify(&minusAlpha, context, ExpressionNode::ReductionTarget::User);
|
||||
xMinusAlphaPowerTwo = Power::Builder(Parenthesis::Builder(Addition::Builder(Symbol::Builder("x", strlen("x")), minusAlpha)), Rational::Builder(2));
|
||||
} else {
|
||||
PoincareHelpers::Simplify(&alpha, context, ExpressionNode::ReductionTarget::User);
|
||||
xMinusAlphaPowerTwo = Power::Builder(Parenthesis::Builder(Subtraction::Builder(Symbol::Builder("x", strlen("x")), alpha)), Rational::Builder(2));
|
||||
}
|
||||
|
||||
Expression xMinusAlphaPowerTwoWithFactor;
|
||||
|
||||
switch (multiplicationTypeForA)
|
||||
{
|
||||
case MultiplicationTypeForA::Nothing:
|
||||
xMinusAlphaPowerTwoWithFactor = xMinusAlphaPowerTwo;
|
||||
break;
|
||||
case MultiplicationTypeForA::Minus:
|
||||
xMinusAlphaPowerTwoWithFactor = Opposite::Builder(xMinusAlphaPowerTwo);
|
||||
break;
|
||||
case MultiplicationTypeForA::Parenthesis:
|
||||
xMinusAlphaPowerTwoWithFactor = Multiplication::Builder(Parenthesis::Builder(a.clone()), xMinusAlphaPowerTwo);
|
||||
break;
|
||||
case MultiplicationTypeForA::Normal:
|
||||
xMinusAlphaPowerTwoWithFactor = Multiplication::Builder(a.clone(), xMinusAlphaPowerTwo);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
Expression canonized;
|
||||
PoincareHelpers::Simplify(&minusBeta, context, ExpressionNode::ReductionTarget::User);
|
||||
Expression beta = getOppositeIfExists(minusBeta, &reductionContext);
|
||||
if (beta.isUninitialized()) {
|
||||
if (minusBeta.type() == ExpressionNode::Type::Addition || minusBeta.type() == ExpressionNode::Type::Subtraction) {
|
||||
canonized = Subtraction::Builder(xMinusAlphaPowerTwoWithFactor, Parenthesis::Builder(minusBeta));
|
||||
} else {
|
||||
canonized = Subtraction::Builder(xMinusAlphaPowerTwoWithFactor, minusBeta);
|
||||
}
|
||||
} else {
|
||||
PoincareHelpers::Simplify(&beta, context, ExpressionNode::ReductionTarget::User);
|
||||
canonized = Addition::Builder(xMinusAlphaPowerTwoWithFactor, beta);
|
||||
}
|
||||
|
||||
Expression x0;
|
||||
Expression x1;
|
||||
|
||||
if (delta.nullStatus(context) == ExpressionNode::NullStatus::Null) {
|
||||
// x0 = x1 = -b/(2a)
|
||||
x0 = Division::Builder(Opposite::Builder(b.clone()), Multiplication::Builder(Rational::Builder(2), a.clone()));
|
||||
m_numberOfSolutions = 1;
|
||||
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::SystemForApproximation);
|
||||
} else {
|
||||
// x0 = (-b-sqrt(delta))/(2a)
|
||||
x0 = Division::Builder(Subtraction::Builder(Opposite::Builder(b.clone()), SquareRoot::Builder(delta.clone())), Multiplication::Builder(Rational::Builder(2), a.clone()));
|
||||
// x1 = (-b+sqrt(delta))/(2a)
|
||||
x1 = Division::Builder(Addition::Builder(Opposite::Builder(b.clone()), SquareRoot::Builder(delta.clone())), Multiplication::Builder(Rational::Builder(2), a.clone()));
|
||||
m_numberOfSolutions = 2;
|
||||
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::SystemForApproximation);
|
||||
PoincareHelpers::Simplify(&x1, context, ExpressionNode::ReductionTarget::SystemForApproximation);
|
||||
if (x0.type() == ExpressionNode::Type::Unreal) {
|
||||
assert(x1.type() == ExpressionNode::Type::Unreal);
|
||||
m_numberOfSolutions = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Expression factorized;
|
||||
|
||||
if (m_numberOfSolutions == 2) {
|
||||
Expression firstFactor;
|
||||
Expression secondFactor;
|
||||
|
||||
Expression x0Opposite = getOppositeIfExists(x0, &reductionContext);
|
||||
if (x0Opposite.isUninitialized()) {
|
||||
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::User);
|
||||
if (x0.type() == ExpressionNode::Type::Addition || x0.type() == ExpressionNode::Type::Subtraction) {
|
||||
firstFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), Parenthesis::Builder(x0.clone()));
|
||||
} else {
|
||||
firstFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), x0.clone());
|
||||
}
|
||||
} else {
|
||||
if (x0Opposite.type() == ExpressionNode::Type::Addition || x0Opposite.type() == ExpressionNode::Type::Subtraction) {
|
||||
x0Opposite = Parenthesis::Builder(x0Opposite.clone());
|
||||
}
|
||||
firstFactor = Addition::Builder(Symbol::Builder("x", strlen("x")), x0Opposite.clone());
|
||||
}
|
||||
|
||||
Expression x1Opposite = getOppositeIfExists(x1, &reductionContext);
|
||||
if (x1Opposite.isUninitialized()) {
|
||||
PoincareHelpers::Simplify(&x1, context, ExpressionNode::ReductionTarget::User);
|
||||
if (x1.type() == ExpressionNode::Type::Addition || x1.type() == ExpressionNode::Type::Subtraction) {
|
||||
secondFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), Parenthesis::Builder(x1.clone()));
|
||||
} else {
|
||||
secondFactor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), x1.clone());
|
||||
}
|
||||
} else {
|
||||
PoincareHelpers::Simplify(&x1Opposite, context, ExpressionNode::ReductionTarget::User);
|
||||
if (x1Opposite.type() == ExpressionNode::Type::Addition || x1Opposite.type() == ExpressionNode::Type::Subtraction) {
|
||||
x1Opposite = Parenthesis::Builder(x1Opposite.clone());
|
||||
}
|
||||
secondFactor = Addition::Builder(Symbol::Builder("x", strlen("x")), x1Opposite.clone());
|
||||
}
|
||||
|
||||
Expression solutionProduct = Multiplication::Builder(Parenthesis::Builder(firstFactor), Parenthesis::Builder(secondFactor));
|
||||
switch (multiplicationTypeForA)
|
||||
{
|
||||
case MultiplicationTypeForA::Nothing:
|
||||
factorized = solutionProduct;
|
||||
break;
|
||||
case MultiplicationTypeForA::Minus:
|
||||
factorized = Opposite::Builder(solutionProduct);
|
||||
break;
|
||||
case MultiplicationTypeForA::Parenthesis:
|
||||
factorized = Multiplication::Builder(Parenthesis::Builder(a.clone()), solutionProduct);
|
||||
break;
|
||||
case MultiplicationTypeForA::Normal:
|
||||
factorized = Multiplication::Builder(a.clone(), solutionProduct);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
} else if (m_numberOfSolutions == 1) {
|
||||
Expression x0Opposite = getOppositeIfExists(x0, &reductionContext);
|
||||
Expression factor;
|
||||
|
||||
if (x0Opposite.isUninitialized()) {
|
||||
PoincareHelpers::Simplify(&x0, context, ExpressionNode::ReductionTarget::User);
|
||||
if (x0.type() == ExpressionNode::Type::Addition || x0.type() == ExpressionNode::Type::Subtraction) {
|
||||
factor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), Parenthesis::Builder(x0.clone()));
|
||||
} else {
|
||||
factor = Subtraction::Builder(Symbol::Builder("x", strlen("x")), x0.clone());
|
||||
}
|
||||
} else {
|
||||
PoincareHelpers::Simplify(&x0Opposite, context, ExpressionNode::ReductionTarget::User);
|
||||
factor = Addition::Builder(Symbol::Builder("x", strlen("x")), x0Opposite.clone());
|
||||
}
|
||||
|
||||
Expression solutionProduct = Power::Builder(Parenthesis::Builder(factor), Rational::Builder(2));
|
||||
switch (multiplicationTypeForA)
|
||||
{
|
||||
case MultiplicationTypeForA::Nothing:
|
||||
factorized = solutionProduct;
|
||||
break;
|
||||
case MultiplicationTypeForA::Minus:
|
||||
factorized = Opposite::Builder(solutionProduct);
|
||||
break;
|
||||
case MultiplicationTypeForA::Parenthesis:
|
||||
factorized = Multiplication::Builder(Parenthesis::Builder(a.clone()), solutionProduct);
|
||||
break;
|
||||
case MultiplicationTypeForA::Normal:
|
||||
factorized = Multiplication::Builder(a.clone(), solutionProduct);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PoincareHelpers::Simplify(&delta, context, ExpressionNode::ReductionTarget::User);
|
||||
|
||||
m_layouts[0] = PoincareHelpers::CreateLayout(canonized);
|
||||
if (m_numberOfSolutions > 0) {
|
||||
m_layouts[1] = PoincareHelpers::CreateLayout(factorized);
|
||||
m_layouts[2] = PoincareHelpers::CreateLayout(delta);
|
||||
m_layouts[3] = PoincareHelpers::CreateLayout(x0);
|
||||
if (m_numberOfSolutions > 1) {
|
||||
m_layouts[4] = PoincareHelpers::CreateLayout(x1);
|
||||
}
|
||||
} else {
|
||||
m_layouts[1] = PoincareHelpers::CreateLayout(delta);
|
||||
}
|
||||
}
|
||||
|
||||
Expression SecondDegreeListController::getOppositeIfExists(Expression e, Poincare::ExpressionNode::ReductionContext * reductionContext) {
|
||||
if (e.isNumber() && e.sign(reductionContext->context()) == ExpressionNode::Sign::Negative) {
|
||||
Number n = static_cast<Number&>(e);
|
||||
return std::move(n.setSign(ExpressionNode::Sign::Positive));
|
||||
} else if(e.type() == ExpressionNode::Type::Opposite) {
|
||||
return std::move(e.childAtIndex(0).clone());
|
||||
} else if (e.type() == ExpressionNode::Type::Multiplication && e.numberOfChildren() > 0 && e.childAtIndex(0).isNumber() && e.childAtIndex(0).sign(reductionContext->context()) == ExpressionNode::Sign::Negative) {
|
||||
Multiplication m = static_cast<Multiplication&>(e);
|
||||
if (m.childAtIndex(0).type() == ExpressionNode::Type::Rational && static_cast<Rational&>(e).isMinusOne()) {
|
||||
// The negative numeral factor is -1, we just remove it
|
||||
m.removeChildAtIndexInPlace(0);
|
||||
} else {
|
||||
Expression firstChild = m.childAtIndex(0);
|
||||
Number n = static_cast<Number&>(firstChild);
|
||||
m.childAtIndex(0).setChildrenInPlace(n.setSign(ExpressionNode::Sign::Positive));
|
||||
}
|
||||
PoincareHelpers::Simplify(&m, reductionContext->context(), ExpressionNode::ReductionTarget::User);
|
||||
return std::move(m);
|
||||
}
|
||||
return Expression();
|
||||
}
|
||||
|
||||
I18n::Message SecondDegreeListController::messageAtIndex(int index) {
|
||||
if (m_numberOfSolutions > 0) {
|
||||
if (index == 0) {
|
||||
return I18n::Message::CanonicalForm;
|
||||
}
|
||||
if (index == 1) {
|
||||
return I18n::Message::FactorizedForm;
|
||||
}
|
||||
if (index == 2) {
|
||||
return I18n::Message::Discriminant;
|
||||
}
|
||||
if (index == 3) {
|
||||
if (m_numberOfSolutions == 1) {
|
||||
return I18n::Message::OnlyRoot;
|
||||
} else {
|
||||
return I18n::Message::FirstRoot;
|
||||
}
|
||||
}
|
||||
return I18n::Message::SecondRoot;
|
||||
} else {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return I18n::Message::CanonicalForm;
|
||||
default:
|
||||
return I18n::Message::Discriminant;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef CALCULATION_ADDITIONAL_OUTPUTS_SECOND_DEGREE_CONTROLLER_H
|
||||
#define CALCULATION_ADDITIONAL_OUTPUTS_SECOND_DEGREE_CONTROLLER_H
|
||||
|
||||
#include "expressions_list_controller.h"
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
class SecondDegreeListController : public ExpressionsListController {
|
||||
public:
|
||||
SecondDegreeListController(EditExpressionController * editExpressionController) :
|
||||
ExpressionsListController(editExpressionController),
|
||||
m_numberOfSolutions(0) {}
|
||||
|
||||
void setExpression(Poincare::Expression e) override;
|
||||
|
||||
private:
|
||||
Poincare::Expression getOppositeIfExists(Poincare::Expression e, Poincare::ExpressionNode::ReductionContext * reductionContext);
|
||||
I18n::Message messageAtIndex(int index) override;
|
||||
int m_numberOfSolutions;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ namespace Calculation {
|
||||
|
||||
TrigonometryGraphView::TrigonometryGraphView(TrigonometryModel * model) :
|
||||
CurveView(model),
|
||||
m_model(model)
|
||||
m_model(model),
|
||||
m_shouldDisplayTan(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -22,17 +23,33 @@ void TrigonometryGraphView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
drawCurve(ctx, rect, 0.0f, 2.0f*M_PI, M_PI/180.0f, [](float t, void * model, void * context) {
|
||||
return Poincare::Coordinate2D<float>(std::cos(t), std::sin(t));
|
||||
}, nullptr, nullptr, true, Palette::SecondaryText, false);
|
||||
// Draw dashed segment to indicate sine and cosine
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Vertical, c, 0.0f, s, Palette::CalculationTrigoAndComplexForeground, 1, 3);
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Horizontal, s, 0.0f, c, Palette::CalculationTrigoAndComplexForeground, 1, 3);
|
||||
|
||||
if (!m_shouldDisplayTan) {
|
||||
// Draw dashed segment to indicate sine and cosine
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Vertical, c, 0.0f, s, Palette::CalculationTrigoAndComplexForeground, 1, 3);
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Horizontal, s, 0.0f, c, Palette::CalculationTrigoAndComplexForeground, 1, 3);
|
||||
}
|
||||
|
||||
if (m_shouldDisplayTan) {
|
||||
float t = std::tan(m_model->angle());
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Vertical, 1.0f, m_model->yMin(), m_model->yMax(), Palette::SecondaryText, 2);
|
||||
drawSegment(ctx, rect, 0.0f, 0.0f, 1.0f, t, Palette::SecondaryText, false);
|
||||
drawDot(ctx, rect, 1.0f, t, Palette::CalculationTrigoAndComplexForeground, Size::Large);
|
||||
drawLabel(ctx, rect, 0.0f, t, "tan(θ)", Palette::CalculationTrigoAndComplexForeground, CurveView::RelativePosition::Before, CurveView::RelativePosition::None);
|
||||
drawHorizontalOrVerticalSegment(ctx, rect, Axis::Horizontal, t, 0.0f, 1.0f, Palette::CalculationTrigoAndComplexForeground, 1, 3);
|
||||
}
|
||||
|
||||
// Draw angle position on the circle
|
||||
drawDot(ctx, rect, c, s, Palette::CalculationTrigoAndComplexForeground, Size::Large);
|
||||
drawDot(ctx, rect, c, s, m_shouldDisplayTan ? Palette::SecondaryText : Palette::CalculationTrigoAndComplexForeground, m_shouldDisplayTan ? Size::Tiny : Size::Large);
|
||||
// Draw graduations
|
||||
drawLabelsAndGraduations(ctx, rect, Axis::Vertical, false, true);
|
||||
drawLabelsAndGraduations(ctx, rect, Axis::Horizontal, false, true);
|
||||
// Draw labels
|
||||
drawLabel(ctx, rect, 0.0f, s, "sin(θ)", Palette::CalculationTrigoAndComplexForeground, c >= 0.0f ? CurveView::RelativePosition::Before : CurveView::RelativePosition::After, CurveView::RelativePosition::None);
|
||||
drawLabel(ctx, rect, c, 0.0f, "cos(θ)", Palette::CalculationTrigoAndComplexForeground, CurveView::RelativePosition::None, s >= 0.0f ? CurveView::RelativePosition::Before : CurveView::RelativePosition::After);
|
||||
|
||||
if (!m_shouldDisplayTan) {
|
||||
// Draw labels
|
||||
drawLabel(ctx, rect, 0.0f, s, "sin(θ)", Palette::CalculationTrigoAndComplexForeground, c >= 0.0f ? CurveView::RelativePosition::Before : CurveView::RelativePosition::After, CurveView::RelativePosition::None);
|
||||
drawLabel(ctx, rect, c, 0.0f, "cos(θ)", Palette::CalculationTrigoAndComplexForeground, CurveView::RelativePosition::None, s >= 0.0f ? CurveView::RelativePosition::Before : CurveView::RelativePosition::After);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,13 +11,16 @@ class TrigonometryGraphView : public Shared::CurveView {
|
||||
public:
|
||||
TrigonometryGraphView(TrigonometryModel * model);
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
void setShouldDisplayTan(bool shouldDisplayTan) { m_shouldDisplayTan = shouldDisplayTan; };
|
||||
private:
|
||||
TrigonometryModel * m_model;
|
||||
bool m_shouldDisplayTan;
|
||||
};
|
||||
|
||||
class TrigonometryGraphCell : public IllustrationCell {
|
||||
public:
|
||||
TrigonometryGraphCell(TrigonometryModel * model) : m_view(model) {}
|
||||
void setShouldDisplayTan(bool shouldDisplayTan) { m_view.setShouldDisplayTan(shouldDisplayTan); };
|
||||
private:
|
||||
View * view() override { return &m_view; }
|
||||
TrigonometryGraphView m_view;
|
||||
|
||||
@@ -1,16 +1,67 @@
|
||||
#include "trigonometry_list_controller.h"
|
||||
#include "../app.h"
|
||||
#include <poincare_nodes.h>
|
||||
#include "../../shared/poincare_helpers.h"
|
||||
|
||||
using namespace Poincare;
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
void TrigonometryListController::setExpression(Poincare::Expression e) {
|
||||
assert(e.type() == ExpressionNode::Type::Cosine || e.type() == ExpressionNode::Type::Sine);
|
||||
IllustratedListController::setExpression(e.childAtIndex(0));
|
||||
static constexpr int s_fullCircle[] = {
|
||||
360,
|
||||
2,
|
||||
400
|
||||
};
|
||||
|
||||
Poincare::Constant toConstant(Expression e) {
|
||||
return static_cast<Poincare::Constant &>(e);
|
||||
}
|
||||
|
||||
void TrigonometryListController::setExpression(Expression e) {
|
||||
assert(e.type() == ExpressionNode::Type::Cosine || e.type() == ExpressionNode::Type::Sine || e.type() == ExpressionNode::Type::Tangent);
|
||||
bool shouldDisplayTan = e.type() == ExpressionNode::Type::Tangent;
|
||||
m_graphCell.setShouldDisplayTan(shouldDisplayTan);
|
||||
m_model.setShouldDisplayTan(shouldDisplayTan);
|
||||
|
||||
Poincare::Context * context = App::app()->localContext();
|
||||
Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences();
|
||||
Preferences::AngleUnit angleUnit = preferences->angleUnit();
|
||||
|
||||
Expression angleExpression = e.childAtIndex(0);
|
||||
|
||||
Shared::PoincareHelpers::Reduce(&angleExpression, context, Poincare::ExpressionNode::ReductionTarget::SystemForAnalysis);
|
||||
|
||||
if ((angleUnit == Preferences::AngleUnit::Radian
|
||||
&& angleExpression.type() == ExpressionNode::Type::Multiplication
|
||||
&& angleExpression.numberOfChildren() == 2
|
||||
&& angleExpression.childAtIndex(1).type() == ExpressionNode::Type::Constant
|
||||
&& toConstant(angleExpression.childAtIndex(1)).isPi()
|
||||
&& angleExpression.childAtIndex(0).type() == ExpressionNode::Type::Rational)
|
||||
|| ((angleUnit == Preferences::AngleUnit::Degree || angleUnit == Preferences::AngleUnit::Gradian)
|
||||
&& angleExpression.type() == ExpressionNode::Type::Rational)) {
|
||||
|
||||
Expression extracted = angleUnit == Preferences::AngleUnit::Radian ? angleExpression.childAtIndex(0) : angleExpression;
|
||||
Rational r = static_cast<Rational &>(extracted);
|
||||
|
||||
Integer denominator = Integer::Multiplication(r.integerDenominator(), Integer(s_fullCircle[(int) angleUnit]));
|
||||
IntegerDivision division = Integer::Division(r.signedIntegerNumerator(), denominator);
|
||||
|
||||
Integer remainder = division.remainder;
|
||||
|
||||
Expression newAngle;
|
||||
Integer rDenominator = r.integerDenominator();
|
||||
Rational newCoefficient = Rational::Builder(remainder, rDenominator);
|
||||
if (angleUnit == Preferences::AngleUnit::Radian) {
|
||||
angleExpression = Multiplication::Builder(newCoefficient, angleExpression.childAtIndex(1));
|
||||
} else {
|
||||
angleExpression = newCoefficient;
|
||||
}
|
||||
}
|
||||
|
||||
IllustratedListController::setExpression(angleExpression);
|
||||
|
||||
// Fill calculation store
|
||||
Poincare::Context * context = App::app()->localContext();
|
||||
m_calculationStore.push("tan(θ)", context, CalculationHeight);
|
||||
m_calculationStore.push("sin(θ)", context, CalculationHeight);
|
||||
m_calculationStore.push("cos(θ)", context, CalculationHeight);
|
||||
m_calculationStore.push("θ", context, CalculationHeight);
|
||||
|
||||
@@ -8,4 +8,22 @@ TrigonometryModel::TrigonometryModel() :
|
||||
{
|
||||
}
|
||||
|
||||
float TrigonometryModel::yMin() const {
|
||||
if (m_shouldDisplayTan) {
|
||||
return -1.1f;
|
||||
}
|
||||
return yCenter() - yHalfRange();
|
||||
}
|
||||
|
||||
float TrigonometryModel::yMax() const {
|
||||
if (m_shouldDisplayTan) {
|
||||
float t = std::tan(angle());
|
||||
if (t <= 1.2f) {
|
||||
return 1.2f;
|
||||
}
|
||||
return 1.2f * std::tan(angle());
|
||||
}
|
||||
return yCenter() + yHalfRange();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@ public:
|
||||
// CurveViewRange
|
||||
float xMin() const override { return -k_xHalfRange; }
|
||||
float xMax() const override { return k_xHalfRange; }
|
||||
float yMin() const override { return yCenter() - yHalfRange(); }
|
||||
float yMax() const override { return yCenter() + yHalfRange(); }
|
||||
float yMin() const override;
|
||||
float yMax() const override;
|
||||
|
||||
void setAngle(float f) { m_angle = f; }
|
||||
float angle() const { return m_angle*(float)M_PI/(float)Poincare::Trigonometry::PiInAngleUnit(Poincare::Preferences::sharedPreferences()->angleUnit()); }
|
||||
void setShouldDisplayTan(bool shouldDisplayTan) { m_shouldDisplayTan = shouldDisplayTan; }
|
||||
private:
|
||||
constexpr static float k_xHalfRange = 2.1f;
|
||||
// We center the yRange around the semi-circle where the angle is
|
||||
@@ -33,6 +34,7 @@ private:
|
||||
float yHalfRange() const { return IllustratedListController::k_illustrationHeight*k_xHalfRange/(Ion::Display::Width - Metric::PopUpRightMargin - Metric::PopUpLeftMargin); }
|
||||
|
||||
float m_angle;
|
||||
bool m_shouldDisplayTan;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -12,115 +12,86 @@ using namespace Shared;
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
|
||||
UnitListController::UnitListController(EditExpressionController * editExpressionController) :
|
||||
ExpressionsListController(editExpressionController),
|
||||
m_dimensionMessage(I18n::Message::Default)
|
||||
{
|
||||
m_dimensionCell.setMessageFont(KDFont::LargeFont);
|
||||
}
|
||||
|
||||
bool UnitListController::handleEvent(Ion::Events::Event event) {
|
||||
if (selectedRow() == 0 && (event == Ion::Events::OK || event == Ion::Events::EXE)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// HACK: Change the selected row (prevent some bugs when OK is pressed)
|
||||
selectRow(selectedRow() - 1);
|
||||
bool value = ListController::handleEvent(event);
|
||||
selectRow(selectedRow() + 1);
|
||||
return value;
|
||||
}
|
||||
|
||||
void UnitListController::setExpression(Poincare::Expression e) {
|
||||
ExpressionsListController::setExpression(e);
|
||||
assert(!m_expression.isUninitialized());
|
||||
// Reinitialize m_memoizedExpressions
|
||||
for (size_t i = 0; i < k_maxNumberOfCells; i++) {
|
||||
m_memoizedExpressions[i] = Expression();
|
||||
}
|
||||
static_assert(k_maxNumberOfRows >= 3, "k_maxNumberOfRows must be greater than 3");
|
||||
|
||||
size_t numberOfMemoizedExpressions = 0;
|
||||
// 1. First rows: miscellaneous classic units for some dimensions
|
||||
Poincare::Expression expressions[k_maxNumberOfRows];
|
||||
// Initialize expressions
|
||||
for (size_t i = 0; i < k_maxNumberOfRows; i++) {
|
||||
expressions[i] = Expression();
|
||||
}
|
||||
m_dimensionMessage = I18n::Message::Default;
|
||||
|
||||
/* 1. First rows: miscellaneous classic units for some dimensions, in both
|
||||
* metric and imperial units. */
|
||||
Expression copy = m_expression.clone();
|
||||
Expression units;
|
||||
// Reduce to be able to recognize units
|
||||
PoincareHelpers::Reduce(©, App::app()->localContext(), ExpressionNode::ReductionTarget::User);
|
||||
copy = copy.removeUnit(&units);
|
||||
bool requireSimplification = false;
|
||||
bool canChangeUnitPrefix = false;
|
||||
PoincareHelpers::ReduceAndRemoveUnit(©, App::app()->localContext(), ExpressionNode::ReductionTarget::User, &units);
|
||||
double value = Shared::PoincareHelpers::ApproximateToScalar<double>(copy, App::app()->localContext());
|
||||
ExpressionNode::ReductionContext reductionContext(
|
||||
App::app()->localContext(),
|
||||
Preferences::sharedPreferences()->complexFormat(),
|
||||
Preferences::sharedPreferences()->angleUnit(),
|
||||
GlobalPreferences::sharedGlobalPreferences()->unitFormat(),
|
||||
ExpressionNode::ReductionTarget::User,
|
||||
ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined);
|
||||
int numberOfExpressions = Unit::SetAdditionalExpressionsAndMessage(units, value, expressions, k_maxNumberOfRows, reductionContext, &m_dimensionMessage);
|
||||
|
||||
if (Unit::IsSISpeed(units)) {
|
||||
// 1.a. Turn speed into km/h
|
||||
m_memoizedExpressions[numberOfMemoizedExpressions++] = UnitConvert::Builder(
|
||||
m_expression.clone(),
|
||||
Multiplication::Builder(
|
||||
Unit::Kilometer(),
|
||||
Power::Builder(
|
||||
Unit::Hour(),
|
||||
Rational::Builder(-1)
|
||||
)
|
||||
)
|
||||
);
|
||||
requireSimplification = true; // Simplify the conversion
|
||||
} else if (Unit::IsSIVolume(units)) {
|
||||
// 1.b. Turn volume into L
|
||||
m_memoizedExpressions[numberOfMemoizedExpressions++] = UnitConvert::Builder(
|
||||
m_expression.clone(),
|
||||
Unit::Liter()
|
||||
);
|
||||
requireSimplification = true; // Simplify the conversion
|
||||
canChangeUnitPrefix = true; // Pick best prefix (mL)
|
||||
} else if (Unit::IsSIEnergy(units)) {
|
||||
// 1.c. Turn energy into Wh
|
||||
m_memoizedExpressions[numberOfMemoizedExpressions++] = UnitConvert::Builder(
|
||||
m_expression.clone(),
|
||||
Multiplication::Builder(
|
||||
Unit::Watt(),
|
||||
Unit::Hour()
|
||||
)
|
||||
);
|
||||
m_memoizedExpressions[numberOfMemoizedExpressions++] = UnitConvert::Builder(
|
||||
m_expression.clone(),
|
||||
Unit::ElectronVolt()
|
||||
);
|
||||
requireSimplification = true; // Simplify the conversion
|
||||
canChangeUnitPrefix = true; // Pick best prefix (kWh)
|
||||
} else if (Unit::IsSITime(units)) {
|
||||
// Turn time into ? year + ? month + ? day + ? h + ? min + ? s
|
||||
double value = Shared::PoincareHelpers::ApproximateToScalar<double>(copy, App::app()->localContext());
|
||||
m_memoizedExpressions[numberOfMemoizedExpressions++] = Unit::BuildTimeSplit(value, App::app()->localContext(), Preferences::sharedPreferences()->complexFormat(), Preferences::sharedPreferences()->angleUnit());
|
||||
}
|
||||
// 1.d. Simplify and tune prefix of all computed expressions
|
||||
size_t currentExpressionIndex = 0;
|
||||
while (currentExpressionIndex < numberOfMemoizedExpressions) {
|
||||
assert(!m_memoizedExpressions[currentExpressionIndex].isUninitialized());
|
||||
if (requireSimplification) {
|
||||
Shared::PoincareHelpers::Simplify(&m_memoizedExpressions[currentExpressionIndex], App::app()->localContext(), ExpressionNode::ReductionTarget::User);
|
||||
}
|
||||
if (canChangeUnitPrefix) {
|
||||
Expression newUnits;
|
||||
// Reduce to be able to removeUnit
|
||||
PoincareHelpers::Reduce(&m_memoizedExpressions[currentExpressionIndex], App::app()->localContext(), ExpressionNode::ReductionTarget::User);
|
||||
m_memoizedExpressions[currentExpressionIndex] = m_memoizedExpressions[currentExpressionIndex].removeUnit(&newUnits);
|
||||
double value = Shared::PoincareHelpers::ApproximateToScalar<double>(m_memoizedExpressions[currentExpressionIndex], App::app()->localContext());
|
||||
ExpressionNode::ReductionContext reductionContext(
|
||||
App::app()->localContext(),
|
||||
Preferences::sharedPreferences()->complexFormat(),
|
||||
Preferences::sharedPreferences()->angleUnit(),
|
||||
ExpressionNode::ReductionTarget::User,
|
||||
ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined);
|
||||
Unit::ChooseBestPrefixForValue(&newUnits, &value, reductionContext);
|
||||
m_memoizedExpressions[currentExpressionIndex] = Multiplication::Builder(Number::FloatNumber(value), newUnits);
|
||||
}
|
||||
currentExpressionIndex++;
|
||||
}
|
||||
// 2. SI units only
|
||||
assert(numberOfExpressions < k_maxNumberOfRows - 1);
|
||||
expressions[numberOfExpressions] = m_expression.clone();
|
||||
Shared::PoincareHelpers::Simplify(&expressions[numberOfExpressions], App::app()->localContext(), ExpressionNode::ReductionTarget::User, Poincare::ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition, Poincare::ExpressionNode::UnitConversion::InternationalSystem);
|
||||
numberOfExpressions++;
|
||||
|
||||
// 2. IS units only
|
||||
assert(numberOfMemoizedExpressions < k_maxNumberOfCells - 1);
|
||||
m_memoizedExpressions[numberOfMemoizedExpressions] = m_expression.clone();
|
||||
Shared::PoincareHelpers::Simplify(&m_memoizedExpressions[numberOfMemoizedExpressions], App::app()->localContext(), ExpressionNode::ReductionTarget::User, Poincare::ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition, Poincare::ExpressionNode::UnitConversion::InternationalSystem);
|
||||
numberOfMemoizedExpressions++;
|
||||
|
||||
// 3. Get rid of duplicates
|
||||
/* 3. Get rid of duplicates
|
||||
* We find duplicates by comparing the serializations, to eliminate
|
||||
* expressions that only differ by the types of their number nodes. */
|
||||
Expression reduceExpression = m_expression.clone();
|
||||
// Make m_expression compareable to m_memoizedExpressions (turn BasedInteger into Rational for instance)
|
||||
// Make m_expression comparable to expressions (turn BasedInteger into Rational for instance)
|
||||
Shared::PoincareHelpers::Simplify(&reduceExpression, App::app()->localContext(), ExpressionNode::ReductionTarget::User, Poincare::ExpressionNode::SymbolicComputation::ReplaceAllDefinedSymbolsWithDefinition, Poincare::ExpressionNode::UnitConversion::None);
|
||||
currentExpressionIndex = 1;
|
||||
while (currentExpressionIndex < numberOfMemoizedExpressions) {
|
||||
int currentExpressionIndex = 0;
|
||||
while (currentExpressionIndex < numberOfExpressions) {
|
||||
bool duplicateFound = false;
|
||||
for (size_t i = 0; i < currentExpressionIndex + 1; i++) {
|
||||
// Compare the currentExpression to all previous memoized expressions and to m_expression
|
||||
Expression comparedExpression = i == currentExpressionIndex ? reduceExpression : m_memoizedExpressions[i];
|
||||
constexpr int buffersSize = Constant::MaxSerializedExpressionSize;
|
||||
char buffer1[buffersSize];
|
||||
int size1 = PoincareHelpers::Serialize(expressions[currentExpressionIndex], buffer1, buffersSize);
|
||||
for (int i = 0; i < currentExpressionIndex + 1; i++) {
|
||||
// Compare the currentExpression to all previous expressions and to m_expression
|
||||
Expression comparedExpression = i == currentExpressionIndex ? reduceExpression : expressions[i];
|
||||
assert(!comparedExpression.isUninitialized());
|
||||
if (comparedExpression.isIdenticalTo(m_memoizedExpressions[currentExpressionIndex])) {
|
||||
numberOfMemoizedExpressions--;
|
||||
char buffer2[buffersSize];
|
||||
int size2 = PoincareHelpers::Serialize(comparedExpression, buffer2, buffersSize);
|
||||
if (size1 == size2 && strcmp(buffer1, buffer2) == 0) {
|
||||
numberOfExpressions--;
|
||||
// Shift next expressions
|
||||
for (size_t j = currentExpressionIndex; j < numberOfMemoizedExpressions; j++) {
|
||||
m_memoizedExpressions[j] = m_memoizedExpressions[j+1];
|
||||
for (int j = currentExpressionIndex; j < numberOfExpressions; j++) {
|
||||
expressions[j] = expressions[j+1];
|
||||
}
|
||||
// Remove last expression
|
||||
m_memoizedExpressions[numberOfMemoizedExpressions] = Expression();
|
||||
expressions[numberOfExpressions] = Expression();
|
||||
// The current expression has been discarded, no need to increment the current index
|
||||
duplicateFound = true;
|
||||
break;
|
||||
@@ -131,21 +102,50 @@ void UnitListController::setExpression(Poincare::Expression e) {
|
||||
currentExpressionIndex++;
|
||||
}
|
||||
}
|
||||
// Memoize layouts
|
||||
for (size_t i = 0; i < k_maxNumberOfRows; i++) {
|
||||
if (!expressions[i].isUninitialized()) {
|
||||
m_layouts[i] = Shared::PoincareHelpers::CreateLayout(expressions[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int UnitListController::numberOfRows() const {
|
||||
int nbOfRows = 0;
|
||||
for (size_t i = 0; i < k_maxNumberOfCells; i++) {
|
||||
if (!m_memoizedExpressions[i].isUninitialized()) {
|
||||
nbOfRows++;
|
||||
}
|
||||
}
|
||||
return nbOfRows;
|
||||
int messageRow = m_dimensionMessage != I18n::Message::Default ? 1 : 0;
|
||||
return ExpressionsListController::numberOfRows() + messageRow;
|
||||
}
|
||||
|
||||
void UnitListController::computeLayoutAtIndex(int index) {
|
||||
assert(!m_memoizedExpressions[index].isUninitialized());
|
||||
m_layouts[index] = Shared::PoincareHelpers::CreateLayout(m_memoizedExpressions[index]);
|
||||
void UnitListController::willDisplayCellForIndex(HighlightCell * cell, int index) {
|
||||
if (index == 0) {
|
||||
MessageTableCell<> * messageTableCell = (MessageTableCell<> *)cell;
|
||||
messageTableCell->setMessage(m_dimensionMessage);
|
||||
} else {
|
||||
ExpressionsListController::willDisplayCellForIndex(cell, index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
KDCoordinate UnitListController::rowHeight(int index) {
|
||||
if (index == 0) {
|
||||
return 35;
|
||||
} else {
|
||||
return ExpressionsListController::rowHeight(index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
HighlightCell * UnitListController::reusableCell(int index, int type) {
|
||||
if (type == 0) {
|
||||
return ExpressionsListController::reusableCell(index, type);
|
||||
} else {
|
||||
return &m_dimensionCell;
|
||||
}
|
||||
}
|
||||
|
||||
int UnitListController::typeAtLocation(int i, int j) {
|
||||
if (j == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return ExpressionsListController::typeAtLocation(i, j - 1);
|
||||
}
|
||||
}
|
||||
|
||||
I18n::Message UnitListController::messageAtIndex(int index) {
|
||||
|
||||
@@ -7,18 +7,23 @@ namespace Calculation {
|
||||
|
||||
class UnitListController : public ExpressionsListController {
|
||||
public:
|
||||
UnitListController(EditExpressionController * editExpressionController) :
|
||||
ExpressionsListController(editExpressionController) {}
|
||||
UnitListController(EditExpressionController * editExpressionController);
|
||||
|
||||
/* Responder */
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
|
||||
void setExpression(Poincare::Expression e) override;
|
||||
|
||||
//ListViewDataSource
|
||||
int reusableCellCount(int type) override { return type == 0 ? ExpressionsListController::reusableCellCount(type) : 1; }
|
||||
HighlightCell * reusableCell(int index, int type) override;
|
||||
KDCoordinate rowHeight(int j) override;
|
||||
int typeAtLocation(int i, int j) override;
|
||||
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
|
||||
int numberOfRows() const override;
|
||||
|
||||
private:
|
||||
void computeLayoutAtIndex(int index) override;
|
||||
I18n::Message messageAtIndex(int index) override;
|
||||
// Memoization of expressions
|
||||
mutable Poincare::Expression m_memoizedExpressions[k_maxNumberOfCells];
|
||||
I18n::Message m_dimensionMessage;
|
||||
MessageTableCell<> m_dimensionCell;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ App * App::Snapshot::unpack(Container * container) {
|
||||
|
||||
void App::Snapshot::reset() {
|
||||
m_calculationStore.deleteAll();
|
||||
m_cacheBuffer[0] = 0;
|
||||
m_cacheBufferInformation = 0;
|
||||
}
|
||||
|
||||
App::Descriptor * App::Snapshot::descriptor() {
|
||||
@@ -38,14 +40,14 @@ App::Descriptor * App::Snapshot::descriptor() {
|
||||
return &descriptor;
|
||||
}
|
||||
|
||||
void App::Snapshot::tidy() {
|
||||
m_calculationStore.tidy();
|
||||
App::Snapshot::Snapshot() : m_calculationStore(m_calculationBuffer, k_calculationBufferSize)
|
||||
{
|
||||
}
|
||||
|
||||
App::App(Snapshot * snapshot) :
|
||||
ExpressionFieldDelegateApp(snapshot, &m_editExpressionController),
|
||||
m_historyController(&m_editExpressionController, snapshot->calculationStore()),
|
||||
m_editExpressionController(&m_modalViewController, this, &m_historyController, snapshot->calculationStore())
|
||||
m_editExpressionController(&m_modalViewController, this, snapshot->cacheBuffer(), snapshot->cacheBufferInformationAddress(), &m_historyController, snapshot->calculationStore())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -73,4 +75,14 @@ bool App::isAcceptableExpression(const Poincare::Expression expression) {
|
||||
return !expression.isUninitialized();
|
||||
}
|
||||
|
||||
void App::didBecomeActive(Window * window) {
|
||||
m_editExpressionController.restoreInput();
|
||||
Shared::ExpressionFieldDelegateApp::didBecomeActive(window);
|
||||
}
|
||||
|
||||
void App::willBecomeInactive() {
|
||||
m_editExpressionController.memoizeInput();
|
||||
Shared::ExpressionFieldDelegateApp::willBecomeInactive();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "history_controller.h"
|
||||
#include "../shared/text_field_delegate_app.h"
|
||||
#include <escher.h>
|
||||
#include "../shared/shared_app.h"
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
@@ -18,15 +19,22 @@ public:
|
||||
App::Descriptor::ExaminationLevel examinationLevel() override;
|
||||
const Image * icon() override;
|
||||
};
|
||||
class Snapshot : public ::App::Snapshot {
|
||||
class Snapshot : public ::SharedApp::Snapshot {
|
||||
public:
|
||||
Snapshot();
|
||||
App * unpack(Container * container) override;
|
||||
void reset() override;
|
||||
Descriptor * descriptor() override;
|
||||
CalculationStore * calculationStore() { return &m_calculationStore; }
|
||||
char * cacheBuffer() { return m_cacheBuffer; }
|
||||
size_t * cacheBufferInformationAddress() { return &m_cacheBufferInformation; }
|
||||
private:
|
||||
void tidy() override;
|
||||
CalculationStore m_calculationStore;
|
||||
// Set the size of the buffer needed to store the calculations
|
||||
static constexpr int k_calculationBufferSize = 10 * (sizeof(Calculation) + Calculation::k_numberOfExpressions * Constant::MaxSerializedExpressionSize + sizeof(Calculation *));
|
||||
char m_calculationBuffer[k_calculationBufferSize];
|
||||
char m_cacheBuffer[EditExpressionController::k_cacheBufferSize];
|
||||
size_t m_cacheBufferInformation;
|
||||
};
|
||||
static App * app() {
|
||||
return static_cast<App *>(Container::activeApp());
|
||||
@@ -36,9 +44,12 @@ public:
|
||||
bool layoutFieldDidReceiveEvent(::LayoutField * layoutField, Ion::Events::Event event) override;
|
||||
// TextFieldDelegateApp
|
||||
bool isAcceptableExpression(const Poincare::Expression expression) override;
|
||||
|
||||
private:
|
||||
App(Snapshot * snapshot);
|
||||
HistoryController m_historyController;
|
||||
void didBecomeActive(Window * window) override;
|
||||
void willBecomeInactive() override;
|
||||
EditExpressionController m_editExpressionController;
|
||||
};
|
||||
|
||||
|
||||
@@ -7,3 +7,14 @@ BinaryBase = "Binär"
|
||||
PrimeFactors = "Primfaktoren"
|
||||
MixedFraction = "Gemischte Zahl"
|
||||
EuclideanDivision = "Division mit Rest"
|
||||
AdditionalDeterminant = "Determinante"
|
||||
AdditionalInverse = "Inverse"
|
||||
AdditionalRowEchelonForm = "Stufenform"
|
||||
AdditionalReducedRowEchelonForm = "Reduzierte Stufenform"
|
||||
AdditionalTrace = "Spur"
|
||||
CanonicalForm = "Kanonische Form"
|
||||
FactorizedForm = "Factorisierte Form"
|
||||
Discriminant = "Diskriminante"
|
||||
OnlyRoot = "Wurzel"
|
||||
FirstRoot = "Erste Wurzel"
|
||||
SecondRoot = "Zweite Wurzel"
|
||||
|
||||
@@ -7,3 +7,14 @@ BinaryBase = "Binary"
|
||||
PrimeFactors = "Prime factors"
|
||||
MixedFraction = "Mixed fraction"
|
||||
EuclideanDivision = "Euclidean division"
|
||||
AdditionalDeterminant = "Determinant"
|
||||
AdditionalInverse = "Inverse"
|
||||
AdditionalRowEchelonForm = "Row echelon form"
|
||||
AdditionalReducedRowEchelonForm = "Reduced row echelon form"
|
||||
AdditionalTrace = "Trace"
|
||||
CanonicalForm = "Canonical form"
|
||||
FactorizedForm = "Factorized form"
|
||||
Discriminant = "Discriminant"
|
||||
OnlyRoot = "Root"
|
||||
FirstRoot = "First root"
|
||||
SecondRoot = "Second root"
|
||||
|
||||
@@ -7,3 +7,14 @@ BinaryBase = "Binario"
|
||||
PrimeFactors = "Factores primos"
|
||||
MixedFraction = "Fracción mixta"
|
||||
EuclideanDivision = "División euclidiana"
|
||||
AdditionalDeterminant = "Determinante"
|
||||
AdditionalInverse = "Inversa"
|
||||
AdditionalRowEchelonForm = "Matriz escalonada"
|
||||
AdditionalReducedRowEchelonForm = "Matriz escalonada reducida"
|
||||
AdditionalTrace = "Traza"
|
||||
CanonicalForm = "Forma canónica"
|
||||
FactorizedForm = "Forma factorizada"
|
||||
Discriminant = "Discriminante"
|
||||
OnlyRoot = "Raíz"
|
||||
FirstRoot = "Primera raíz"
|
||||
SecondRoot = "Segunda raíz"
|
||||
|
||||
@@ -7,3 +7,14 @@ BinaryBase = "Binaire"
|
||||
PrimeFactors = "Facteurs premiers"
|
||||
MixedFraction = "Fraction mixte"
|
||||
EuclideanDivision = "Division euclidienne"
|
||||
AdditionalDeterminant = "Déterminant"
|
||||
AdditionalInverse = "Inverse"
|
||||
AdditionalRowEchelonForm = "Forme échelonnée"
|
||||
AdditionalReducedRowEchelonForm = "Forme échelonnée réduite"
|
||||
AdditionalTrace = "Trace"
|
||||
CanonicalForm = "Forme canonique"
|
||||
FactorizedForm = "Forme factorisée"
|
||||
Discriminant = "Discriminant"
|
||||
OnlyRoot = "Racine"
|
||||
FirstRoot = "Première racine"
|
||||
SecondRoot = "Seconde racine"
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
CalculApp = "Számolás"
|
||||
CalculAppCapital = "SZÁMOLÁS"
|
||||
AdditionalResults = "További eredmények"
|
||||
DecimalBase = "Decimális"
|
||||
HexadecimalBase = "Hexadecimális"
|
||||
BinaryBase = "Kétkomponensü"
|
||||
PrimeFactors = "Alapvetö tényezök"
|
||||
MixedFraction = "Vegyes frakció"
|
||||
EuclideanDivision = "Euklideszi osztás"
|
||||
CalculApp = "Számolás"
|
||||
CalculAppCapital = "SZÁMOLÁS"
|
||||
AdditionalResults = "További eredmények"
|
||||
DecimalBase = "Decimális"
|
||||
HexadecimalBase = "Hexadecimális"
|
||||
BinaryBase = "Bináris"
|
||||
PrimeFactors = "Alapvetö tényezök"
|
||||
MixedFraction = "Vegyes frakció"
|
||||
EuclideanDivision = "Euklideszi osztás"
|
||||
AdditionalDeterminant = "Meghatározó"
|
||||
AdditionalInverse = "inverz"
|
||||
AdditionalRowEchelonForm = "Sor echelon forma"
|
||||
AdditionalReducedRowEchelonForm = "Csökkentett sorú Echelon forma"
|
||||
AdditionalTrace = "Nyomkövetés"
|
||||
CanonicalForm = "Kanonikus forma"
|
||||
FactorizedForm = "Factorizált forma"
|
||||
Discriminant = "Discriminant"
|
||||
OnlyRoot = "Gyökér"
|
||||
FirstRoot = "Első gyökér"
|
||||
SecondRoot = "Második gyökér"
|
||||
|
||||
@@ -4,6 +4,17 @@ AdditionalResults = "Risultati complementari"
|
||||
DecimalBase = "Decimale"
|
||||
HexadecimalBase = "Esadecimale"
|
||||
BinaryBase = "Binario"
|
||||
PrimeFactors = "Fattori primi"
|
||||
PrimeFactors = "Fattorizzazione"
|
||||
MixedFraction = "Frazione mista"
|
||||
EuclideanDivision = "Divisione euclidea"
|
||||
AdditionalDeterminant = "Determinante"
|
||||
AdditionalInverse = "Inversa"
|
||||
AdditionalRowEchelonForm = "Matrice a scalini"
|
||||
AdditionalReducedRowEchelonForm = "Matrice ridotta a scalini"
|
||||
AdditionalTrace = "Traccia"
|
||||
CanonicalForm = "Forma canonica"
|
||||
FactorizedForm = "Forma fattorizzata"
|
||||
Discriminant = "Discriminante"
|
||||
OnlyRoot = "Radice"
|
||||
FirstRoot = "Prima radice"
|
||||
SecondRoot = "Seconda radice"
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
CalculApp = "Calculatie"
|
||||
CalculAppCapital = "CALCULATIE"
|
||||
AdditionalResults = "Bijkomende resultaten"
|
||||
CalculApp = "Rekenen"
|
||||
CalculAppCapital = "REKENEN"
|
||||
AdditionalResults = "Aanvullende resultaten"
|
||||
DecimalBase = "Decimaal"
|
||||
HexadecimalBase = "Hexadecimaal"
|
||||
BinaryBase = "Binaire"
|
||||
PrimeFactors = "Priemfactoren"
|
||||
BinaryBase = "Binair"
|
||||
PrimeFactors = "Ontbinding"
|
||||
MixedFraction = "Gemengde breuk"
|
||||
EuclideanDivision = "Geheeltallige deling"
|
||||
AdditionalDeterminant = "Determinant"
|
||||
AdditionalInverse = "Inverse"
|
||||
AdditionalRowEchelonForm = "Echelonvorm"
|
||||
AdditionalReducedRowEchelonForm = "Gereduceerde echelonvorm"
|
||||
AdditionalTrace = "Spoor"
|
||||
CanonicalForm = "Canonische vorm"
|
||||
FactorizedForm = "Factorized vorm"
|
||||
Discriminant = "Discriminant"
|
||||
OnlyRoot = "Wortel"
|
||||
FirstRoot = "Eerste wortel"
|
||||
SecondRoot = "Tweede wortel"
|
||||
|
||||
@@ -4,6 +4,17 @@ AdditionalResults = "Resultados adicionais"
|
||||
DecimalBase = "Decimal"
|
||||
HexadecimalBase = "Hexadecimal"
|
||||
BinaryBase = "Binário"
|
||||
PrimeFactors = "Fatores primos"
|
||||
PrimeFactors = "Fatorização"
|
||||
MixedFraction = "Fração mista"
|
||||
EuclideanDivision = "Divisão euclidiana"
|
||||
AdditionalDeterminant = "Determinante"
|
||||
AdditionalInverse = "Matriz inversa"
|
||||
AdditionalRowEchelonForm = "Matriz escalonada"
|
||||
AdditionalReducedRowEchelonForm = "Matriz escalonada reduzida"
|
||||
AdditionalTrace = "Traço"
|
||||
CanonicalForm = "Forma canónica"
|
||||
FactorizedForm = "Factorized form"
|
||||
Discriminant = "Discriminante"
|
||||
OnlyRoot = "Raiz"
|
||||
FirstRoot = "Primeira raiz"
|
||||
SecondRoot = "Segunda raiz"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <poincare/undefined.h>
|
||||
#include <poincare/unit.h>
|
||||
#include <poincare/unreal.h>
|
||||
#include <poincare/symbol_abstract.h>
|
||||
#include <string.h>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
@@ -169,7 +170,8 @@ Calculation::DisplayOutput Calculation::displayOutput(Context * context) {
|
||||
ExpressionNode::Type::Sum,
|
||||
ExpressionNode::Type::Derivative,
|
||||
ExpressionNode::Type::ConfidenceInterval,
|
||||
ExpressionNode::Type::PredictionInterval
|
||||
ExpressionNode::Type::PredictionInterval,
|
||||
ExpressionNode::Type::Sequence
|
||||
};
|
||||
return e.isOfType(approximateOnlyTypes, sizeof(approximateOnlyTypes)/sizeof(ExpressionNode::Type));
|
||||
}, context)
|
||||
@@ -218,7 +220,7 @@ Calculation::EqualSign Calculation::exactAndApproximateDisplayedOutputsAreEqual(
|
||||
Preferences * preferences = Preferences::sharedPreferences();
|
||||
// TODO: complex format should not be needed here (as it is not used to create layouts)
|
||||
Preferences::ComplexFormat complexFormat = Expression::UpdatedComplexFormatWithTextInput(preferences->complexFormat(), m_inputText);
|
||||
m_equalSign = Expression::ParsedExpressionsAreEqual(exactOutputText(), approximateOutputText(NumberOfSignificantDigits::UserDefined), context, complexFormat, preferences->angleUnit()) ? EqualSign::Equal : EqualSign::Approximation;
|
||||
m_equalSign = Expression::ParsedExpressionsAreEqual(exactOutputText(), approximateOutputText(NumberOfSignificantDigits::UserDefined), context, complexFormat, preferences->angleUnit(), GlobalPreferences::sharedGlobalPreferences()->unitFormat()) ? EqualSign::Equal : EqualSign::Approximation;
|
||||
return m_equalSign;
|
||||
} else {
|
||||
/* Do not override m_equalSign in case there is enough room in the pool
|
||||
@@ -249,37 +251,18 @@ Calculation::AdditionalInformationType Calculation::additionalInformationType(Co
|
||||
* - > input: 2cos(2) - cos(2)
|
||||
* > output: cos(2)
|
||||
*/
|
||||
if (input().isDefinedCosineOrSine(context, complexFormat, preferences->angleUnit()) || o.isDefinedCosineOrSine(context, complexFormat, preferences->angleUnit())) {
|
||||
return AdditionalInformationType::Trigonometry;
|
||||
if (i.isDefinedCosineOrSineOrTangent(context, complexFormat, preferences->angleUnit())) {
|
||||
return AdditionalInformationType::TrigonometryInput;
|
||||
}
|
||||
if (o.isDefinedCosineOrSineOrTangent(context, complexFormat, preferences->angleUnit())) {
|
||||
return AdditionalInformationType::TrigonometryOutput;
|
||||
}
|
||||
if (o.hasUnit()) {
|
||||
Expression unit;
|
||||
PoincareHelpers::Reduce(&o,
|
||||
App::app()->localContext(),
|
||||
ExpressionNode::ReductionTarget::User,
|
||||
ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined,
|
||||
ExpressionNode::UnitConversion::None);
|
||||
o = o.removeUnit(&unit);
|
||||
// There might be no unit in the end, if the reduction was interrupted.
|
||||
if (!unit.isUninitialized()) {
|
||||
if (Unit::IsSI(unit)) {
|
||||
if (Unit::IsSISpeed(unit) || Unit::IsSIVolume(unit) || Unit::IsSIEnergy(unit)) {
|
||||
/* All these units will provide misc. classic representatives in
|
||||
* addition to the SI unit in additional information. */
|
||||
return AdditionalInformationType::Unit;
|
||||
}
|
||||
if (Unit::IsSITime(unit)) {
|
||||
/* If the number of seconds is above 60s, we can write it in the form
|
||||
* of an addition: 23_min + 12_s for instance. */
|
||||
double value = Shared::PoincareHelpers::ApproximateToScalar<double>(o, App::app()->localContext());
|
||||
if (value > Unit::SecondsPerMinute) {
|
||||
return AdditionalInformationType::Unit;
|
||||
}
|
||||
}
|
||||
return AdditionalInformationType::None;
|
||||
}
|
||||
return AdditionalInformationType::Unit;
|
||||
}
|
||||
PoincareHelpers::ReduceAndRemoveUnit(&o, App::app()->localContext(), ExpressionNode::ReductionTarget::User, &unit, ExpressionNode::SymbolicComputation::ReplaceAllSymbolsWithDefinitionsOrUndefined, ExpressionNode::UnitConversion::None);
|
||||
UnitNode::Vector<int> vector = UnitNode::Vector<int>::FromBaseUnits(unit);
|
||||
const Unit::Representative * representative = Unit::Representative::RepresentativeForDimension(vector);
|
||||
return representative != nullptr ? AdditionalInformationType::Unit : AdditionalInformationType::None;
|
||||
}
|
||||
if (o.isBasedIntegerCappedBy(k_maximalIntegerWithAdditionalInformation)) {
|
||||
return AdditionalInformationType::Integer;
|
||||
@@ -291,6 +274,12 @@ Calculation::AdditionalInformationType Calculation::additionalInformationType(Co
|
||||
if (o.hasDefinedComplexApproximation(context, complexFormat, preferences->angleUnit())) {
|
||||
return AdditionalInformationType::Complex;
|
||||
}
|
||||
if (o.type() == ExpressionNode::Type::Matrix) {
|
||||
return AdditionalInformationType::Matrix;
|
||||
}
|
||||
if (o.polynomialDegree(context, "x") == 2) {
|
||||
return AdditionalInformationType::SecondDegree;
|
||||
}
|
||||
return AdditionalInformationType::None;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ class CalculationStore;
|
||||
class Calculation {
|
||||
friend CalculationStore;
|
||||
public:
|
||||
static constexpr int k_numberOfExpressions = 4;
|
||||
enum class EqualSign : uint8_t {
|
||||
Unknown,
|
||||
Approximation,
|
||||
@@ -38,8 +39,11 @@ public:
|
||||
None = 0,
|
||||
Integer,
|
||||
Rational,
|
||||
Trigonometry,
|
||||
SecondDegree,
|
||||
TrigonometryInput,
|
||||
TrigonometryOutput,
|
||||
Unit,
|
||||
Matrix,
|
||||
Complex
|
||||
};
|
||||
static bool DisplaysExact(DisplayOutput d) { return d != DisplayOutput::ApproximateOnly; }
|
||||
@@ -48,7 +52,7 @@ public:
|
||||
* calculations instead of clearing less space, then fail to serialize, clear
|
||||
* more space, fail to serialize, clear more space, etc., until reaching
|
||||
* sufficient free space. */
|
||||
static int MinimalSize() { return sizeof(uint8_t) + 2*sizeof(KDCoordinate) + sizeof(uint8_t) + 3*Constant::MaxSerializedExpressionSize; }
|
||||
static int MinimalSize() { return sizeof(uint8_t) + 2*sizeof(KDCoordinate) + sizeof(uint8_t) + 3*Constant::MaxSerializedExpressionSize + sizeof(Calculation *); }
|
||||
|
||||
Calculation() :
|
||||
m_displayOutput(DisplayOutput::Unknown),
|
||||
@@ -93,10 +97,8 @@ public:
|
||||
// Additional Information
|
||||
AdditionalInformationType additionalInformationType(Poincare::Context * context);
|
||||
private:
|
||||
static constexpr int maxWidth = 314;
|
||||
static constexpr int k_numberOfExpressions = 4;
|
||||
static constexpr KDCoordinate k_heightComputationFailureHeight = 50;
|
||||
static constexpr const char * k_maximalIntegerWithAdditionalInformation = "10000000000000000";
|
||||
static constexpr const char * k_maximalIntegerWithAdditionalInformation = "18446744073709551617"; // 2^64 + 1
|
||||
|
||||
void setHeights(KDCoordinate height, KDCoordinate expandedHeight);
|
||||
|
||||
|
||||
@@ -7,63 +7,125 @@
|
||||
#include "../exam_mode_configuration.h"
|
||||
#include <assert.h>
|
||||
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <apps/shared/global_context.h>
|
||||
|
||||
static KDCoordinate dummyHeight(::Calculation::Calculation * c, bool expanded) {
|
||||
bool b;
|
||||
Poincare::Layout l = c->createExactOutputLayout(&b);
|
||||
if (!b) {
|
||||
l=c->createInputLayout();
|
||||
}
|
||||
KDSize s = l.layoutSize();
|
||||
const int bordersize = 10;
|
||||
int h = s.height() + bordersize;
|
||||
const int maxheight = 64;
|
||||
if (h > maxheight) {
|
||||
return maxheight;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
extern void * last_calculation_history;
|
||||
void * last_calculation_history = 0;
|
||||
const char * retrieve_calc_history();
|
||||
|
||||
#endif
|
||||
|
||||
using namespace Poincare;
|
||||
using namespace Shared;
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
CalculationStore::CalculationStore() :
|
||||
m_bufferEnd(m_buffer),
|
||||
CalculationStore::CalculationStore(char * buffer, int size) :
|
||||
m_buffer(buffer),
|
||||
m_bufferSize(size),
|
||||
m_calculationAreaEnd(m_buffer),
|
||||
m_numberOfCalculations(0),
|
||||
m_slidedBuffer(false),
|
||||
m_indexOfFirstMemoizedCalculationPointer(0)
|
||||
m_trashIndex(-1)
|
||||
{
|
||||
resetMemoizedModelsAfterCalculationIndex(-1);
|
||||
}
|
||||
|
||||
ExpiringPointer<Calculation> CalculationStore::calculationAtIndex(int i) {
|
||||
assert(!m_slidedBuffer);
|
||||
assert(i >= 0 && i < m_numberOfCalculations);
|
||||
assert(m_indexOfFirstMemoizedCalculationPointer >= 0);
|
||||
if (i >= m_indexOfFirstMemoizedCalculationPointer && i < m_indexOfFirstMemoizedCalculationPointer + k_numberOfMemoizedCalculationPointers) {
|
||||
// The calculation is within the range of memoized calculations
|
||||
Calculation * c = m_memoizedCalculationPointers[i-m_indexOfFirstMemoizedCalculationPointer];
|
||||
if (c != nullptr) {
|
||||
// The pointer was memoized
|
||||
return ExpiringPointer<Calculation>(c);
|
||||
assert(m_buffer != nullptr);
|
||||
assert(m_bufferSize > 0);
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
if (last_calculation_history == 0){
|
||||
// Restore from scriptstore
|
||||
const char * buf=retrieve_calc_history();
|
||||
if (buf) {
|
||||
Shared::GlobalContext globalContext;
|
||||
char * ptr=(char *)buf;
|
||||
for (;*ptr;) {
|
||||
for (;*ptr;++ptr) {
|
||||
if (*ptr=='\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
char c = *ptr;
|
||||
*ptr=0;
|
||||
if (ptr > buf) {
|
||||
push(buf,&globalContext, dummyHeight);
|
||||
}
|
||||
*ptr = c;
|
||||
++ptr;
|
||||
buf = ptr;
|
||||
}
|
||||
}
|
||||
c = bufferCalculationAtIndex(i);
|
||||
m_memoizedCalculationPointers[i-m_indexOfFirstMemoizedCalculationPointer] = c;
|
||||
return c;
|
||||
last_calculation_history = (void *) this;
|
||||
}
|
||||
// Slide the memoization buffer
|
||||
if (i >= m_indexOfFirstMemoizedCalculationPointer) {
|
||||
// Slide the memoization buffer to the left
|
||||
memmove(m_memoizedCalculationPointers, m_memoizedCalculationPointers+1, (k_numberOfMemoizedCalculationPointers - 1) * sizeof(Calculation *));
|
||||
m_memoizedCalculationPointers[k_numberOfMemoizedCalculationPointers - 1] = nullptr;
|
||||
m_indexOfFirstMemoizedCalculationPointer++;
|
||||
} else {
|
||||
// Slide the memoization buffer to the right
|
||||
memmove(m_memoizedCalculationPointers+1, m_memoizedCalculationPointers, (k_numberOfMemoizedCalculationPointers - 1) * sizeof(Calculation *));
|
||||
m_memoizedCalculationPointers[0] = nullptr;
|
||||
m_indexOfFirstMemoizedCalculationPointer--;
|
||||
}
|
||||
return calculationAtIndex(i);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns an expiring pointer to the calculation of index i, and ignore the trash
|
||||
ExpiringPointer<Calculation> CalculationStore::calculationAtIndex(int i) {
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
last_calculation_history = (void *) this;
|
||||
#endif
|
||||
if (m_trashIndex == -1 || i < m_trashIndex) {
|
||||
return realCalculationAtIndex(i);
|
||||
} else {
|
||||
return realCalculationAtIndex(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns an expiring pointer to the real calculation of index i
|
||||
ExpiringPointer<Calculation> CalculationStore::realCalculationAtIndex(int i) {
|
||||
assert(i >= 0 && i < m_numberOfCalculations);
|
||||
// m_buffer is the address of the oldest calculation in calculation store
|
||||
Calculation * c = (Calculation *) m_buffer;
|
||||
if (i != m_numberOfCalculations-1) {
|
||||
// The calculation we want is not the oldest one so we get its pointer
|
||||
c = *reinterpret_cast<Calculation**>(addressOfPointerToCalculationOfIndex(i+1));
|
||||
}
|
||||
return ExpiringPointer<Calculation>(c);
|
||||
}
|
||||
|
||||
// Pushes an expression in the store
|
||||
ExpiringPointer<Calculation> CalculationStore::push(const char * text, Context * context, HeightComputer heightComputer) {
|
||||
/* Compute ans now, before the buffer is slided and before the calculation
|
||||
emptyTrash();
|
||||
/* Compute ans now, before the buffer is updated and before the calculation
|
||||
* might be deleted */
|
||||
Expression ans = ansExpression(context);
|
||||
|
||||
// Prepare the buffer for the new calculation
|
||||
int minSize = Calculation::MinimalSize();
|
||||
assert(k_bufferSize > minSize);
|
||||
while (remainingBufferSize() < minSize || m_numberOfCalculations > k_maxNumberOfCalculations) {
|
||||
deleteLastCalculation();
|
||||
/* Prepare the buffer for the new calculation
|
||||
* The minimal size to store the new calculation is the minimal size of a calculation plus the pointer to its end */
|
||||
int minSize = Calculation::MinimalSize() + sizeof(Calculation *);
|
||||
assert(m_bufferSize > minSize);
|
||||
while (remainingBufferSize() < minSize) {
|
||||
// If there is no more space to store a calculation, we delete the oldest one
|
||||
deleteOldestCalculation();
|
||||
}
|
||||
char * newCalculationsLocation = slideCalculationsToEndOfBuffer();
|
||||
char * nextSerializationLocation = m_buffer;
|
||||
|
||||
// Getting the adresses of the limits of the free space
|
||||
char * beginingOfFreeSpace = (char *)m_calculationAreaEnd;
|
||||
char * endOfFreeSpace = beginingOfMemoizationArea();
|
||||
char * previousCalc = beginingOfFreeSpace;
|
||||
|
||||
// Add the beginning of the calculation
|
||||
{
|
||||
@@ -71,23 +133,23 @@ ExpiringPointer<Calculation> CalculationStore::push(const char * text, Context *
|
||||
* available, so this memmove will not overide anything. */
|
||||
Calculation newCalc = Calculation();
|
||||
size_t calcSize = sizeof(newCalc);
|
||||
memmove(nextSerializationLocation, &newCalc, calcSize);
|
||||
nextSerializationLocation += calcSize;
|
||||
memcpy(beginingOfFreeSpace, &newCalc, calcSize);
|
||||
beginingOfFreeSpace += calcSize;
|
||||
}
|
||||
|
||||
/* Add the input expression.
|
||||
* We do not store directly the text entered by the user because we do not
|
||||
* want to keep Ans symbol in the calculation store. */
|
||||
const char * inputSerialization = nextSerializationLocation;
|
||||
const char * inputSerialization = beginingOfFreeSpace;
|
||||
{
|
||||
Expression input = Expression::Parse(text, context).replaceSymbolWithExpression(Symbol::Ans(), ans);
|
||||
if (!pushSerializeExpression(input, nextSerializationLocation, &newCalculationsLocation)) {
|
||||
if (!pushSerializeExpression(input, beginingOfFreeSpace, &endOfFreeSpace)) {
|
||||
/* If the input does not fit in the store (event if the current
|
||||
* calculation is the only calculation), just replace the calculation with
|
||||
* undef. */
|
||||
return emptyStoreAndPushUndef(context, heightComputer);
|
||||
}
|
||||
nextSerializationLocation += strlen(nextSerializationLocation) + 1;
|
||||
beginingOfFreeSpace += strlen(beginingOfFreeSpace) + 1;
|
||||
}
|
||||
|
||||
// Compute and serialize the outputs
|
||||
@@ -110,30 +172,27 @@ ExpiringPointer<Calculation> CalculationStore::push(const char * text, Context *
|
||||
if (i == numberOfOutputs - 1) {
|
||||
numberOfSignificantDigits = Poincare::Preferences::sharedPreferences()->numberOfSignificantDigits();
|
||||
}
|
||||
if (!pushSerializeExpression(outputs[i], nextSerializationLocation, &newCalculationsLocation, numberOfSignificantDigits)) {
|
||||
/* If the exat/approximate output does not fit in the store (event if the
|
||||
if (!pushSerializeExpression(outputs[i], beginingOfFreeSpace, &endOfFreeSpace, numberOfSignificantDigits)) {
|
||||
/* If the exact/approximate output does not fit in the store (event if the
|
||||
* current calculation is the only calculation), replace the output with
|
||||
* undef if it fits, else replace the whole calcualtion with undef. */
|
||||
* undef if it fits, else replace the whole calculation with undef. */
|
||||
Expression undef = Undefined::Builder();
|
||||
if (!pushSerializeExpression(undef, nextSerializationLocation, &newCalculationsLocation)) {
|
||||
if (!pushSerializeExpression(undef, beginingOfFreeSpace, &endOfFreeSpace)) {
|
||||
return emptyStoreAndPushUndef(context, heightComputer);
|
||||
}
|
||||
}
|
||||
nextSerializationLocation += strlen(nextSerializationLocation) + 1;
|
||||
beginingOfFreeSpace += strlen(beginingOfFreeSpace) + 1;
|
||||
}
|
||||
}
|
||||
// Storing the pointer of the end of the new calculation
|
||||
memcpy(endOfFreeSpace-sizeof(Calculation*),&beginingOfFreeSpace,sizeof(beginingOfFreeSpace));
|
||||
|
||||
// Restore the other calculations
|
||||
size_t slideSize = m_buffer + k_bufferSize - newCalculationsLocation;
|
||||
memcpy(nextSerializationLocation, newCalculationsLocation, slideSize);
|
||||
m_slidedBuffer = false;
|
||||
// The new calculation is now stored
|
||||
m_numberOfCalculations++;
|
||||
m_bufferEnd+= nextSerializationLocation - m_buffer;
|
||||
|
||||
// Clean the memoization
|
||||
resetMemoizedModelsAfterCalculationIndex(-1);
|
||||
|
||||
ExpiringPointer<Calculation> calculation = ExpiringPointer<Calculation>(reinterpret_cast<Calculation *>(m_buffer));
|
||||
// The end of the calculation storage area is updated
|
||||
m_calculationAreaEnd += beginingOfFreeSpace - previousCalc;
|
||||
ExpiringPointer<Calculation> calculation = ExpiringPointer<Calculation>(reinterpret_cast<Calculation *>(previousCalc));
|
||||
/* Heights are computed now to make sure that the display output is decided
|
||||
* accordingly to the remaining size in the Poincare pool. Once it is, it
|
||||
* can't change anymore: the calculation heights are fixed which ensures that
|
||||
@@ -144,36 +203,51 @@ ExpiringPointer<Calculation> CalculationStore::push(const char * text, Context *
|
||||
return calculation;
|
||||
}
|
||||
|
||||
// Delete the calculation of index i
|
||||
void CalculationStore::deleteCalculationAtIndex(int i) {
|
||||
if (m_trashIndex != -1) {
|
||||
emptyTrash();
|
||||
}
|
||||
m_trashIndex = i;
|
||||
}
|
||||
|
||||
// Delete the calculation of index i, internal algorithm
|
||||
void CalculationStore::realDeleteCalculationAtIndex(int i) {
|
||||
assert(i >= 0 && i < m_numberOfCalculations);
|
||||
assert(!m_slidedBuffer);
|
||||
ExpiringPointer<Calculation> calcI = calculationAtIndex(i);
|
||||
char * nextCalc = reinterpret_cast<char *>(calcI->next());
|
||||
assert(m_bufferEnd >= nextCalc);
|
||||
size_t slidingSize = m_bufferEnd - nextCalc;
|
||||
memmove((char *)(calcI.pointer()), nextCalc, slidingSize);
|
||||
m_bufferEnd -= (nextCalc - (char *)(calcI.pointer()));
|
||||
m_numberOfCalculations--;
|
||||
resetMemoizedModelsAfterCalculationIndex(i);
|
||||
}
|
||||
|
||||
void CalculationStore::deleteAll() {
|
||||
/* We might call deleteAll because the app closed due to a pool allocation
|
||||
* failure, so we cannot assert that m_slidedBuffer is false. */
|
||||
m_slidedBuffer = false;
|
||||
m_bufferEnd = m_buffer;
|
||||
m_numberOfCalculations = 0;
|
||||
resetMemoizedModelsAfterCalculationIndex(-1);
|
||||
}
|
||||
|
||||
void CalculationStore::tidy() {
|
||||
if (m_slidedBuffer) {
|
||||
deleteAll();
|
||||
if (i == 0) {
|
||||
ExpiringPointer<Calculation> lastCalculationPointer = realCalculationAtIndex(0);
|
||||
m_calculationAreaEnd = (char *)(lastCalculationPointer.pointer());
|
||||
m_numberOfCalculations--;
|
||||
return;
|
||||
}
|
||||
resetMemoizedModelsAfterCalculationIndex(-1);
|
||||
char * calcI = (char *)realCalculationAtIndex(i).pointer();
|
||||
char * nextCalc = (char *) realCalculationAtIndex(i-1).pointer();
|
||||
assert(m_calculationAreaEnd >= nextCalc);
|
||||
size_t slidingSize = m_calculationAreaEnd - nextCalc;
|
||||
// Slide the i-1 most recent calculations right after the i+1'th
|
||||
memmove(calcI, nextCalc, slidingSize);
|
||||
m_calculationAreaEnd -= nextCalc - calcI;
|
||||
// Recompute pointer to calculations after the i'th
|
||||
recomputeMemoizedPointersAfterCalculationIndex(i);
|
||||
m_numberOfCalculations--;
|
||||
}
|
||||
|
||||
// Delete the oldest calculation in the store and returns the amount of space freed by the operation
|
||||
size_t CalculationStore::deleteOldestCalculation() {
|
||||
char * oldBufferEnd = (char *) m_calculationAreaEnd;
|
||||
realDeleteCalculationAtIndex(numberOfCalculations()-1);
|
||||
char * newBufferEnd = (char *) m_calculationAreaEnd;
|
||||
return oldBufferEnd - newBufferEnd;
|
||||
}
|
||||
|
||||
// Delete all calculations
|
||||
void CalculationStore::deleteAll() {
|
||||
m_trashIndex = -1;
|
||||
m_calculationAreaEnd = m_buffer;
|
||||
m_numberOfCalculations = 0;
|
||||
}
|
||||
|
||||
// Replace "Ans" by its expression
|
||||
Expression CalculationStore::ansExpression(Context * context) {
|
||||
if (numberOfCalculations() == 0) {
|
||||
return Rational::Builder(0);
|
||||
@@ -185,99 +259,55 @@ Expression CalculationStore::ansExpression(Context * context) {
|
||||
* parsed), ans is replaced by the approximation output when any Store or
|
||||
* Equal expression appears. */
|
||||
Expression e = mostRecentCalculation->exactOutput();
|
||||
bool exactOuptutInvolvesStoreEqual = e.type() == ExpressionNode::Type::Store || e.type() == ExpressionNode::Type::Equal;
|
||||
if (mostRecentCalculation->input().recursivelyMatches(Expression::IsApproximate, context) || exactOuptutInvolvesStoreEqual) {
|
||||
bool exactOutputInvolvesStoreEqual = e.type() == ExpressionNode::Type::Store || e.type() == ExpressionNode::Type::Equal;
|
||||
if (mostRecentCalculation->input().recursivelyMatches(Expression::IsApproximate, context) || exactOutputInvolvesStoreEqual) {
|
||||
return mostRecentCalculation->approximateOutput(context, Calculation::NumberOfSignificantDigits::Maximal);
|
||||
}
|
||||
return mostRecentCalculation->exactOutput();
|
||||
}
|
||||
|
||||
Calculation * CalculationStore::bufferCalculationAtIndex(int i) {
|
||||
int currentIndex = 0;
|
||||
for (Calculation * c : *this) {
|
||||
if (currentIndex == i) {
|
||||
return c;
|
||||
}
|
||||
currentIndex++;
|
||||
}
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Push converted expression in the buffer
|
||||
bool CalculationStore::pushSerializeExpression(Expression e, char * location, char * * newCalculationsLocation, int numberOfSignificantDigits) {
|
||||
assert(m_slidedBuffer);
|
||||
assert(*newCalculationsLocation <= m_buffer + k_bufferSize);
|
||||
assert(*newCalculationsLocation <= m_buffer + m_bufferSize);
|
||||
bool expressionIsPushed = false;
|
||||
while (true) {
|
||||
size_t locationSize = *newCalculationsLocation - location;
|
||||
expressionIsPushed = (PoincareHelpers::Serialize(e, location, locationSize, numberOfSignificantDigits) < (int)locationSize-1);
|
||||
if (expressionIsPushed || *newCalculationsLocation >= m_buffer + k_bufferSize) {
|
||||
if (expressionIsPushed || *newCalculationsLocation >= m_buffer + m_bufferSize) {
|
||||
break;
|
||||
}
|
||||
*newCalculationsLocation = *newCalculationsLocation + deleteLastCalculation();
|
||||
assert(*newCalculationsLocation <= m_buffer + k_bufferSize);
|
||||
*newCalculationsLocation = *newCalculationsLocation + deleteOldestCalculation();
|
||||
assert(*newCalculationsLocation <= m_buffer + m_bufferSize);
|
||||
}
|
||||
return expressionIsPushed;
|
||||
}
|
||||
|
||||
char * CalculationStore::slideCalculationsToEndOfBuffer() {
|
||||
int calculationsSize = m_bufferEnd - m_buffer;
|
||||
char * calculationsNewPosition = m_buffer + k_bufferSize - calculationsSize;
|
||||
memmove(calculationsNewPosition, m_buffer, calculationsSize);
|
||||
m_slidedBuffer = true;
|
||||
return calculationsNewPosition;
|
||||
void CalculationStore::emptyTrash() {
|
||||
if (m_trashIndex != -1) {
|
||||
realDeleteCalculationAtIndex(m_trashIndex);
|
||||
m_trashIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
size_t CalculationStore::deleteLastCalculation(const char * calculationsStart) {
|
||||
assert(m_numberOfCalculations > 0);
|
||||
size_t result;
|
||||
if (!m_slidedBuffer) {
|
||||
assert(calculationsStart == nullptr);
|
||||
const char * previousBufferEnd = m_bufferEnd;
|
||||
m_bufferEnd = lastCalculationPosition(m_buffer);
|
||||
assert(previousBufferEnd > m_bufferEnd);
|
||||
result = previousBufferEnd - m_bufferEnd;
|
||||
} else {
|
||||
assert(calculationsStart != nullptr);
|
||||
const char * lastCalc = lastCalculationPosition(calculationsStart);
|
||||
assert(*lastCalc == 0);
|
||||
result = m_buffer + k_bufferSize - lastCalc;
|
||||
memmove(const_cast<char *>(calculationsStart + result), calculationsStart, m_buffer + k_bufferSize - calculationsStart - result);
|
||||
}
|
||||
m_numberOfCalculations--;
|
||||
resetMemoizedModelsAfterCalculationIndex(-1);
|
||||
return result;
|
||||
}
|
||||
|
||||
const char * CalculationStore::lastCalculationPosition(const char * calculationsStart) const {
|
||||
assert(calculationsStart >= m_buffer && calculationsStart < m_buffer + k_bufferSize);
|
||||
Calculation * c = reinterpret_cast<Calculation *>(const_cast<char *>(calculationsStart));
|
||||
int calculationIndex = 0;
|
||||
while (calculationIndex < m_numberOfCalculations - 1) {
|
||||
c = c->next();
|
||||
calculationIndex++;
|
||||
}
|
||||
return reinterpret_cast<const char *>(c);
|
||||
}
|
||||
|
||||
Shared::ExpiringPointer<Calculation> CalculationStore::emptyStoreAndPushUndef(Context * context, HeightComputer heightComputer) {
|
||||
/* We end up here as a result of a failed calculation push. The store
|
||||
* attributes are not necessarily clean, so we need to reset them. */
|
||||
m_slidedBuffer = false;
|
||||
deleteAll();
|
||||
return push(Undefined::Name(), context, heightComputer);
|
||||
}
|
||||
|
||||
void CalculationStore::resetMemoizedModelsAfterCalculationIndex(int index) {
|
||||
if (index < m_indexOfFirstMemoizedCalculationPointer) {
|
||||
memset(&m_memoizedCalculationPointers, 0, k_numberOfMemoizedCalculationPointers * sizeof(Calculation *));
|
||||
return;
|
||||
}
|
||||
if (index >= m_indexOfFirstMemoizedCalculationPointer + k_numberOfMemoizedCalculationPointers) {
|
||||
return;
|
||||
}
|
||||
for (int i = index - m_indexOfFirstMemoizedCalculationPointer; i < k_numberOfMemoizedCalculationPointers; i++) {
|
||||
m_memoizedCalculationPointers[i] = nullptr;
|
||||
// Recompute memoized pointers to the calculations after index i
|
||||
void CalculationStore::recomputeMemoizedPointersAfterCalculationIndex(int index) {
|
||||
assert(index < m_numberOfCalculations);
|
||||
// Clear pointer and recompute new ones
|
||||
Calculation * c = realCalculationAtIndex(index).pointer();
|
||||
Calculation * nextCalc;
|
||||
while (index != 0) {
|
||||
nextCalc = c->next();
|
||||
memcpy(addressOfPointerToCalculationOfIndex(index), &nextCalc, sizeof(Calculation *));
|
||||
c = nextCalc;
|
||||
index--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,37 +7,49 @@
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
/* To optimize the storage space, we use one big buffer for all calculations.
|
||||
*
|
||||
* The previous solution was to keep 10 calculations, each containing 3 buffers
|
||||
* (for input and outputs). To optimize the storage, we then wanted to put all
|
||||
* outputs in a cache where they could be deleted to add a new entry, and
|
||||
* recomputed on cache miss. However, the computation depends too much on the
|
||||
* state of the memory for this to be possible. For instance:
|
||||
* 6->a
|
||||
* a+1
|
||||
* Perform some big computations that remove a+1 from the cache
|
||||
* Delete a from the variable box.
|
||||
* Scroll up to display a+1 : a does not exist anymore so the outputs won't be
|
||||
* recomputed correctly.
|
||||
*
|
||||
* Now we do not cap the number of calculations and just delete the oldests to
|
||||
* create space for a new calculation. */
|
||||
/*
|
||||
To optimize the storage space, we use one big buffer for all calculations.
|
||||
The calculations are stored one after another while pointers to the end of each
|
||||
calculation are stored at the end of the buffer, in the opposite direction.
|
||||
By doing so, we can memoize every calculation entered while not limiting
|
||||
the number of calculation stored in the buffer.
|
||||
|
||||
If the remaining space is too small for storing a new calculation, we
|
||||
delete the oldest one.
|
||||
|
||||
Memory layout :
|
||||
<- Available space for new calculations ->
|
||||
+--------------------------------------------------------------------------------------------------------------------+
|
||||
| | | | | | | | | |
|
||||
| Calculation 3 | Calculation 2 | Calculation 1 | Calculation O | |p0|p1|p2|p3|
|
||||
| Oldest | | | | | | | | |
|
||||
+--------------------------------------------------------------------------------------------------------------------+
|
||||
^ ^ ^ ^ ^ ^
|
||||
m_buffer p3 p2 p1 p0 a
|
||||
|
||||
m_calculationAreaEnd = p0
|
||||
a = addressOfPointerToCalculation(0)
|
||||
*/
|
||||
|
||||
class CalculationStore {
|
||||
public:
|
||||
CalculationStore();
|
||||
CalculationStore(char * buffer, int size);
|
||||
Shared::ExpiringPointer<Calculation> calculationAtIndex(int i);
|
||||
typedef KDCoordinate (*HeightComputer)(Calculation * c, bool expanded);
|
||||
Shared::ExpiringPointer<Calculation> push(const char * text, Poincare::Context * context, HeightComputer heightComputer);
|
||||
void deleteCalculationAtIndex(int i);
|
||||
void deleteAll();
|
||||
int numberOfCalculations() const { return m_numberOfCalculations; }
|
||||
int remainingBufferSize() const { assert(m_calculationAreaEnd >= m_buffer); return m_bufferSize - (m_calculationAreaEnd - m_buffer) - m_numberOfCalculations*sizeof(Calculation*); }
|
||||
int numberOfCalculations() const { return m_numberOfCalculations - (m_trashIndex != -1); }
|
||||
Poincare::Expression ansExpression(Poincare::Context * context);
|
||||
void tidy();
|
||||
int bufferSize() { return m_bufferSize; }
|
||||
void reinsertTrash() { m_trashIndex = -1; }
|
||||
|
||||
private:
|
||||
static constexpr int k_maxNumberOfCalculations = 25;
|
||||
static constexpr int k_bufferSize = 10 * Calculation::k_numberOfExpressions * Constant::MaxSerializedExpressionSize;
|
||||
void emptyTrash();
|
||||
Shared::ExpiringPointer<Calculation> realCalculationAtIndex(int i);
|
||||
void realDeleteCalculationAtIndex(int i);
|
||||
|
||||
class CalculationIterator {
|
||||
public:
|
||||
@@ -53,26 +65,23 @@ private:
|
||||
};
|
||||
|
||||
CalculationIterator begin() const { return CalculationIterator(m_buffer); }
|
||||
CalculationIterator end() const { return CalculationIterator(m_bufferEnd); }
|
||||
CalculationIterator end() const { return CalculationIterator(m_calculationAreaEnd); }
|
||||
|
||||
Calculation * bufferCalculationAtIndex(int i);
|
||||
int remainingBufferSize() const { assert(m_bufferEnd >= m_buffer); return k_bufferSize - (m_bufferEnd - m_buffer); }
|
||||
bool pushSerializeExpression(Poincare::Expression e, char * location, char * * newCalculationsLocation, int numberOfSignificantDigits = Poincare::PrintFloat::k_numberOfStoredSignificantDigits);
|
||||
char * slideCalculationsToEndOfBuffer(); // returns the new position of the calculations
|
||||
size_t deleteLastCalculation(const char * calculationsStart = nullptr);
|
||||
const char * lastCalculationPosition(const char * calculationsStart) const;
|
||||
Shared::ExpiringPointer<Calculation> emptyStoreAndPushUndef(Poincare::Context * context, HeightComputer heightComputer);
|
||||
|
||||
char m_buffer[k_bufferSize];
|
||||
const char * m_bufferEnd;
|
||||
char * m_buffer;
|
||||
int m_bufferSize;
|
||||
const char * m_calculationAreaEnd;
|
||||
int m_numberOfCalculations;
|
||||
bool m_slidedBuffer;
|
||||
int m_trashIndex;
|
||||
|
||||
size_t deleteOldestCalculation();
|
||||
char * addressOfPointerToCalculationOfIndex(int i) {return m_buffer + m_bufferSize - (m_numberOfCalculations - i)*sizeof(Calculation *);}
|
||||
|
||||
// Memoization
|
||||
static constexpr int k_numberOfMemoizedCalculationPointers = 10;
|
||||
void resetMemoizedModelsAfterCalculationIndex(int index);
|
||||
int m_indexOfFirstMemoizedCalculationPointer;
|
||||
mutable Calculation * m_memoizedCalculationPointers[k_numberOfMemoizedCalculationPointers];
|
||||
char * beginingOfMemoizationArea() {return addressOfPointerToCalculationOfIndex(0);};
|
||||
void recomputeMemoizedPointersAfterCalculationIndex(int index);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -38,13 +38,14 @@ void EditExpressionController::ContentView::reload() {
|
||||
markRectAsDirty(bounds());
|
||||
}
|
||||
|
||||
EditExpressionController::EditExpressionController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, HistoryController * historyController, CalculationStore * calculationStore) :
|
||||
EditExpressionController::EditExpressionController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, char * cacheBuffer, size_t * cacheBufferInformation, HistoryController * historyController, CalculationStore * calculationStore) :
|
||||
ViewController(parentResponder),
|
||||
m_cacheBuffer(cacheBuffer),
|
||||
m_cacheBufferInformation(cacheBufferInformation),
|
||||
m_historyController(historyController),
|
||||
m_calculationStore(calculationStore),
|
||||
m_contentView(this, static_cast<CalculationSelectableTableView *>(m_historyController->view()), inputEventHandlerDelegate, this, this)
|
||||
{
|
||||
m_cacheBuffer[0] = 0;
|
||||
}
|
||||
|
||||
void EditExpressionController::insertTextBody(const char * text) {
|
||||
@@ -58,6 +59,24 @@ void EditExpressionController::didBecomeFirstResponder() {
|
||||
Container::activeApp()->setFirstResponder(m_contentView.expressionField());
|
||||
}
|
||||
|
||||
void EditExpressionController::restoreInput() {
|
||||
m_contentView.expressionField()->restoreContent(m_cacheBuffer, *m_cacheBufferInformation);
|
||||
clearCacheBuffer();
|
||||
}
|
||||
|
||||
void EditExpressionController::memoizeInput() {
|
||||
*m_cacheBufferInformation = m_contentView.expressionField()->moveCursorAndDumpContent(m_cacheBuffer, k_cacheBufferSize);
|
||||
}
|
||||
|
||||
bool EditExpressionController::handleEvent(Ion::Events::Event event) {
|
||||
if (event == Ion::Events::ShiftBack) {
|
||||
m_historyController->reinsertTrash();
|
||||
m_historyController->reload();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EditExpressionController::viewWillAppear() {
|
||||
m_historyController->viewWillAppear();
|
||||
}
|
||||
@@ -128,7 +147,7 @@ bool EditExpressionController::inputViewDidReceiveEvent(Ion::Events::Event event
|
||||
}
|
||||
if (event == Ion::Events::Up) {
|
||||
if (m_calculationStore->numberOfCalculations() > 0) {
|
||||
m_cacheBuffer[0] = 0;
|
||||
clearCacheBuffer();
|
||||
m_contentView.expressionField()->setEditing(false, false);
|
||||
Container::activeApp()->setFirstResponder(m_historyController);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "../shared/text_field_delegate.h"
|
||||
#include "../shared/layout_field_delegate.h"
|
||||
#include "history_controller.h"
|
||||
#include "calculation_store.h"
|
||||
#include "selectable_table_view.h"
|
||||
|
||||
namespace Calculation {
|
||||
@@ -15,11 +14,24 @@ namespace Calculation {
|
||||
/* TODO: implement a split view */
|
||||
class EditExpressionController : public ViewController, public Shared::TextFieldDelegate, public Shared::LayoutFieldDelegate {
|
||||
public:
|
||||
EditExpressionController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, HistoryController * historyController, CalculationStore * calculationStore);
|
||||
EditExpressionController(Responder * parentResponder, InputEventHandlerDelegate * inputEventHandlerDelegate, char * cacheBuffer, size_t * cacheBufferInformation, HistoryController * historyController, CalculationStore * calculationStore);
|
||||
|
||||
/* k_layoutBufferMaxSize dictates the size under which the expression being
|
||||
* edited can be remembered when the user leaves Calculation. */
|
||||
static constexpr int k_layoutBufferMaxSize = 1024;
|
||||
/* k_cacheBufferSize is the size of the array to which m_cacheBuffer points.
|
||||
* It is used both as a way to buffer expression when pushing them the
|
||||
* CalculationStore, and as a storage for the current input when leaving the
|
||||
* application. */
|
||||
static constexpr int k_cacheBufferSize = (k_layoutBufferMaxSize < Constant::MaxSerializedExpressionSize) ? Constant::MaxSerializedExpressionSize : k_layoutBufferMaxSize;
|
||||
|
||||
View * view() override { return &m_contentView; }
|
||||
void didBecomeFirstResponder() override;
|
||||
void viewWillAppear() override;
|
||||
void insertTextBody(const char * text);
|
||||
void restoreInput();
|
||||
void memoizeInput();
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
|
||||
/* TextFieldDelegate */
|
||||
bool textFieldDidReceiveEvent(::TextField * textField, Ion::Events::Event event) override;
|
||||
@@ -47,11 +59,12 @@ private:
|
||||
ExpressionField m_expressionField;
|
||||
};
|
||||
void reloadView();
|
||||
void clearCacheBuffer() { m_cacheBuffer[0] = 0; *m_cacheBufferInformation = 0; }
|
||||
bool inputViewDidReceiveEvent(Ion::Events::Event event, bool shouldDuplicateLastCalculation);
|
||||
bool inputViewDidFinishEditing(const char * text, Poincare::Layout layoutR);
|
||||
bool inputViewDidAbortEditing(const char * text);
|
||||
static constexpr int k_cacheBufferSize = Constant::MaxSerializedExpressionSize;
|
||||
char m_cacheBuffer[k_cacheBufferSize];
|
||||
char * m_cacheBuffer;
|
||||
size_t * m_cacheBufferInformation;
|
||||
HistoryController * m_historyController;
|
||||
CalculationStore * m_calculationStore;
|
||||
ContentView m_contentView;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#include "expression_field.h"
|
||||
#include <poincare/symbol.h>
|
||||
#include <poincare/horizontal_layout.h>
|
||||
#include <poincare/code_point_layout.h>
|
||||
|
||||
using namespace Poincare;
|
||||
namespace Calculation {
|
||||
|
||||
bool ExpressionField::handleEvent(Ion::Events::Event event) {
|
||||
@@ -17,10 +20,34 @@ bool ExpressionField::handleEvent(Ion::Events::Event event) {
|
||||
event == Ion::Events::Power ||
|
||||
event == Ion::Events::Square ||
|
||||
event == Ion::Events::Division ||
|
||||
event == Ion::Events::Sto)) {
|
||||
event == Ion::Events::Sto ||
|
||||
event == Ion::Events::EE)) {
|
||||
handleEventWithText(Poincare::Symbol::k_ans);
|
||||
}
|
||||
return(::ExpressionField::handleEvent(event));
|
||||
if (event == Ion::Events::Minus
|
||||
&& isEditing()
|
||||
&& fieldHasOnlyAMinus()) {
|
||||
setText(Poincare::Symbol::k_ans);
|
||||
}
|
||||
return (::ExpressionField::handleEvent(event));
|
||||
}
|
||||
|
||||
bool ExpressionField::fieldHasOnlyAMinus() const {
|
||||
if (editionIsInTextField()) {
|
||||
const char *inputBuffer = m_textField.draftTextBuffer();
|
||||
return (inputBuffer[0] == '-' && inputBuffer[1] == '\0');
|
||||
}
|
||||
Layout layout = m_layoutField.layout();
|
||||
if (layout.type() == LayoutNode::Type::HorizontalLayout && layout.numberOfChildren() == 1) {
|
||||
Layout child = layout.childAtIndex(0);
|
||||
if (child.type() == LayoutNode::Type::CodePointLayout) {
|
||||
CodePointLayout &codePointLayout = static_cast<CodePointLayout &>(child);
|
||||
if (codePointLayout.codePoint() == '-'){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ public:
|
||||
}
|
||||
protected:
|
||||
bool handleEvent(Ion::Events::Event event) override;
|
||||
private:
|
||||
bool fieldHasOnlyAMinus() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -16,8 +16,10 @@ HistoryController::HistoryController(EditExpressionController * editExpressionCo
|
||||
m_complexController(editExpressionController),
|
||||
m_integerController(editExpressionController),
|
||||
m_rationalController(editExpressionController),
|
||||
m_secondDegreeController(editExpressionController),
|
||||
m_trigonometryController(editExpressionController),
|
||||
m_unitController(editExpressionController)
|
||||
m_unitController(editExpressionController),
|
||||
m_matrixController(editExpressionController)
|
||||
{
|
||||
for (int i = 0; i < k_maxNumberOfDisplayedRows; i++) {
|
||||
m_calculationHistory[i].setParentResponder(&m_selectableTableView);
|
||||
@@ -99,17 +101,21 @@ bool HistoryController::handleEvent(Ion::Events::Event event) {
|
||||
Expression e = calculationAtIndex(focusRow)->exactOutput();
|
||||
if (additionalInfoType == Calculation::AdditionalInformationType::Complex) {
|
||||
vc = &m_complexController;
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::Trigonometry) {
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::SecondDegree) {
|
||||
vc = &m_secondDegreeController;
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::TrigonometryInput) {
|
||||
vc = &m_trigonometryController;
|
||||
// Find which of the input or output is the cosine/sine
|
||||
ExpressionNode::Type t = e.type();
|
||||
e = t == ExpressionNode::Type::Cosine || t == ExpressionNode::Type::Sine ? e : calculationAtIndex(focusRow)->input();
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::Integer) {
|
||||
e = calculationAtIndex(focusRow)->input();
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::TrigonometryOutput) {
|
||||
vc = &m_trigonometryController;
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::Integer) {
|
||||
vc = &m_integerController;
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::Rational) {
|
||||
vc = &m_rationalController;
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::Unit) {
|
||||
vc = &m_unitController;
|
||||
} else if (additionalInfoType == Calculation::AdditionalInformationType::Matrix) {
|
||||
vc = &m_matrixController;
|
||||
}
|
||||
if (vc) {
|
||||
vc->setExpression(e);
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
#include "additional_outputs/complex_list_controller.h"
|
||||
#include "additional_outputs/integer_list_controller.h"
|
||||
#include "additional_outputs/rational_list_controller.h"
|
||||
#include "additional_outputs/second_degree_list_controller.h"
|
||||
#include "additional_outputs/trigonometry_list_controller.h"
|
||||
#include "additional_outputs/unit_list_controller.h"
|
||||
#include "additional_outputs/matrix_list_controller.h"
|
||||
|
||||
namespace Calculation {
|
||||
|
||||
@@ -33,6 +35,7 @@ public:
|
||||
int typeAtLocation(int i, int j) override;
|
||||
void setSelectedSubviewType(SubviewType subviewType, bool sameCell, int previousSelectedX = -1, int previousSelectedY = -1) override;
|
||||
void tableViewDidChangeSelectionAndDidScroll(SelectableTableView * t, int previousSelectedCellX, int previousSelectedCellY, bool withinTemporarySelection = false) override;
|
||||
void reinsertTrash() { m_calculationStore->reinsertTrash(); }
|
||||
private:
|
||||
int storeIndex(int i) { return numberOfRows() - i - 1; }
|
||||
Shared::ExpiringPointer<Calculation> calculationAtIndex(int i);
|
||||
@@ -46,8 +49,10 @@ private:
|
||||
ComplexListController m_complexController;
|
||||
IntegerListController m_integerController;
|
||||
RationalListController m_rationalController;
|
||||
SecondDegreeListController m_secondDegreeController;
|
||||
TrigonometryListController m_trigonometryController;
|
||||
UnitListController m_unitController;
|
||||
MatrixListController m_matrixController;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ void HistoryViewCell::reloadSubviewHighlight() {
|
||||
m_ellipsis.setHighlighted(false);
|
||||
if (isHighlighted()) {
|
||||
if (m_dataSource->selectedSubviewType() == HistoryViewCellDataSource::SubviewType::Input) {
|
||||
m_inputView.setExpressionBackgroundColor(Palette::ListCellBackgroundSelected);
|
||||
m_inputView.setExpressionBackgroundColor(Palette::Select);
|
||||
} else if (m_dataSource->selectedSubviewType() == HistoryViewCellDataSource::SubviewType::Output) {
|
||||
m_scrollableOutputView.evenOddCell()->setHighlighted(true);
|
||||
} else {
|
||||
@@ -299,6 +299,7 @@ void HistoryViewCell::setCalculation(Calculation * calculation, bool expanded, b
|
||||
m_calculationDisplayOutput = calculation->displayOutput(context);
|
||||
|
||||
// We must set which subviews are displayed before setLayouts to mark the right rectangle as dirty
|
||||
m_scrollableOutputView.setDisplayableCenter(m_calculationDisplayOutput == Calculation::DisplayOutput::ExactAndApproximate || m_calculationDisplayOutput == Calculation::DisplayOutput::ExactAndApproximateToggle);
|
||||
m_scrollableOutputView.setDisplayCenter(m_calculationDisplayOutput == Calculation::DisplayOutput::ExactAndApproximate || m_calculationExpanded);
|
||||
m_scrollableOutputView.setLayouts(Poincare::Layout(), exactOutputLayout, approximateOutputLayout);
|
||||
I18n::Message equalMessage = calculation->exactAndApproximateDisplayedOutputsAreEqual(context) == Calculation::EqualSign::Equal ? I18n::Message::Equal : I18n::Message::AlmostEqual;
|
||||
|
||||
@@ -5,9 +5,17 @@
|
||||
#include <assert.h>
|
||||
#include "../calculation_store.h"
|
||||
|
||||
typedef ::Calculation::Calculation::DisplayOutput DisplayOutput;
|
||||
typedef ::Calculation::Calculation::EqualSign EqualSign ;
|
||||
typedef ::Calculation::Calculation::NumberOfSignificantDigits NumberOfSignificantDigits;
|
||||
|
||||
using namespace Poincare;
|
||||
using namespace Calculation;
|
||||
|
||||
static constexpr int calculationBufferSize = 10 * (sizeof(::Calculation::Calculation) + ::Calculation::Calculation::k_numberOfExpressions * ::Constant::MaxSerializedExpressionSize + sizeof(::Calculation::Calculation *));
|
||||
char calculationBuffer[calculationBufferSize];
|
||||
|
||||
|
||||
void assert_store_is(CalculationStore * store, const char * * result) {
|
||||
for (int i = 0; i < store->numberOfCalculations(); i++) {
|
||||
quiz_assert(strcmp(store->calculationAtIndex(i)->inputText(), result[i]) == 0);
|
||||
@@ -18,7 +26,7 @@ KDCoordinate dummyHeight(::Calculation::Calculation * c, bool expanded) { return
|
||||
|
||||
QUIZ_CASE(calculation_store) {
|
||||
Shared::GlobalContext globalContext;
|
||||
CalculationStore store;
|
||||
CalculationStore store(calculationBuffer,calculationBufferSize);
|
||||
// Store is now {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
|
||||
const char * result[] = {"9", "8", "7", "6", "5", "4", "3", "2", "1", "0"};
|
||||
for (int i = 0; i < 10; i++) {
|
||||
@@ -29,101 +37,117 @@ QUIZ_CASE(calculation_store) {
|
||||
assert_store_is(&store, result);
|
||||
|
||||
for (int i = 9; i > 0; i = i-2) {
|
||||
store.deleteCalculationAtIndex(i);
|
||||
store.deleteCalculationAtIndex(i);
|
||||
}
|
||||
// Store is now {9, 7, 5, 3, 1}
|
||||
const char * result2[] = {"9", "7", "5", "3", "1"};
|
||||
assert_store_is(&store, result2);
|
||||
|
||||
store.deleteAll();
|
||||
|
||||
// Checking if the store handles correctly the delete of the oldest calculation when full
|
||||
static int minSize = ::Calculation::Calculation::MinimalSize();
|
||||
char text[2] = {'0', 0};
|
||||
while (store.remainingBufferSize() > minSize) {
|
||||
store.push(text, &globalContext, dummyHeight);
|
||||
}
|
||||
int numberOfCalculations1 = store.numberOfCalculations();
|
||||
/* The buffer is now to full to push a new calculation.
|
||||
* Trying to push a new one should delete the oldest one*/
|
||||
store.push(text, &globalContext, dummyHeight);
|
||||
int numberOfCalculations2 = store.numberOfCalculations();
|
||||
// The numberOfCalculations should be the same
|
||||
quiz_assert(numberOfCalculations1 == numberOfCalculations2);
|
||||
store.deleteAll();
|
||||
quiz_assert(store.remainingBufferSize() == store.bufferSize());
|
||||
}
|
||||
|
||||
QUIZ_CASE(calculation_ans) {
|
||||
Shared::GlobalContext globalContext;
|
||||
CalculationStore store;
|
||||
CalculationStore store(calculationBuffer,calculationBufferSize);
|
||||
|
||||
store.push("1+3/4", &globalContext, dummyHeight);
|
||||
store.push("ans+2/3", &globalContext, dummyHeight);
|
||||
Shared::ExpiringPointer<::Calculation::Calculation> lastCalculation = store.calculationAtIndex(0);
|
||||
quiz_assert(lastCalculation->displayOutput(&globalContext) == ::Calculation::Calculation::DisplayOutput::ExactAndApproximate);
|
||||
quiz_assert(lastCalculation->displayOutput(&globalContext) == DisplayOutput::ExactAndApproximate);
|
||||
quiz_assert(strcmp(lastCalculation->exactOutputText(),"29/12") == 0);
|
||||
|
||||
store.push("ans+0.22", &globalContext, dummyHeight);
|
||||
lastCalculation = store.calculationAtIndex(0);
|
||||
quiz_assert(lastCalculation->displayOutput(&globalContext) == ::Calculation::Calculation::DisplayOutput::ExactAndApproximateToggle);
|
||||
quiz_assert(strcmp(lastCalculation->approximateOutputText(::Calculation::Calculation::NumberOfSignificantDigits::Maximal),"2.6366666666667") == 0);
|
||||
quiz_assert(lastCalculation->displayOutput(&globalContext) == DisplayOutput::ExactAndApproximateToggle);
|
||||
quiz_assert(strcmp(lastCalculation->approximateOutputText(NumberOfSignificantDigits::Maximal),"2.6366666666667") == 0);
|
||||
|
||||
store.deleteAll();
|
||||
}
|
||||
|
||||
void assertCalculationIs(const char * input, ::Calculation::Calculation::DisplayOutput display, ::Calculation::Calculation::EqualSign sign, const char * exactOutput, const char * displayedApproximateOutput, const char * storedApproximateOutput, Context * context, CalculationStore * store) {
|
||||
void assertCalculationIs(const char * input, DisplayOutput display, EqualSign sign, const char * exactOutput, const char * displayedApproximateOutput, const char * storedApproximateOutput, Context * context, CalculationStore * store) {
|
||||
store->push(input, context, dummyHeight);
|
||||
Shared::ExpiringPointer<::Calculation::Calculation> lastCalculation = store->calculationAtIndex(0);
|
||||
quiz_assert(lastCalculation->displayOutput(context) == display);
|
||||
if (sign != ::Calculation::Calculation::EqualSign::Unknown) {
|
||||
if (sign != EqualSign::Unknown) {
|
||||
quiz_assert(lastCalculation->exactAndApproximateDisplayedOutputsAreEqual(context) == sign);
|
||||
}
|
||||
if (exactOutput) {
|
||||
quiz_assert_print_if_failure(strcmp(lastCalculation->exactOutputText(), exactOutput) == 0, input);
|
||||
}
|
||||
if (displayedApproximateOutput) {
|
||||
quiz_assert_print_if_failure(strcmp(lastCalculation->approximateOutputText(::Calculation::Calculation::NumberOfSignificantDigits::UserDefined), displayedApproximateOutput) == 0, input);
|
||||
quiz_assert_print_if_failure(strcmp(lastCalculation->approximateOutputText(NumberOfSignificantDigits::UserDefined), displayedApproximateOutput) == 0, input);
|
||||
}
|
||||
if (storedApproximateOutput) {
|
||||
quiz_assert_print_if_failure(strcmp(lastCalculation->approximateOutputText(::Calculation::Calculation::NumberOfSignificantDigits::Maximal), storedApproximateOutput) == 0, input);
|
||||
quiz_assert_print_if_failure(strcmp(lastCalculation->approximateOutputText(NumberOfSignificantDigits::Maximal), storedApproximateOutput) == 0, input);
|
||||
}
|
||||
store->deleteAll();
|
||||
}
|
||||
|
||||
QUIZ_CASE(calculation_significant_digits) {
|
||||
Shared::GlobalContext globalContext;
|
||||
CalculationStore store;
|
||||
CalculationStore store(calculationBuffer,calculationBufferSize);
|
||||
|
||||
assertCalculationIs("123456789", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Approximation, "123456789", "1.234568ᴇ8", "123456789", &globalContext, &store);
|
||||
assertCalculationIs("1234567", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Equal, "1234567", "1234567", "1234567", &globalContext, &store);
|
||||
assertCalculationIs("123456789", DisplayOutput::ExactAndApproximate, EqualSign::Approximation, "123456789", "1.234568ᴇ8", "123456789", &globalContext, &store);
|
||||
assertCalculationIs("1234567", DisplayOutput::ApproximateOnly, EqualSign::Equal, "1234567", "1234567", "1234567", &globalContext, &store);
|
||||
|
||||
}
|
||||
|
||||
QUIZ_CASE(calculation_display_exact_approximate) {
|
||||
Shared::GlobalContext globalContext;
|
||||
CalculationStore store;
|
||||
CalculationStore store(calculationBuffer,calculationBufferSize);
|
||||
|
||||
assertCalculationIs("1/2", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Equal, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("1/3", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Approximation, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("1/0", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, "undef", "undef", "undef", &globalContext, &store);
|
||||
assertCalculationIs("2x-x", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, "undef", "undef", "undef", &globalContext, &store);
|
||||
assertCalculationIs("[[1,2,3]]", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("[[1,x,3]]", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "undef", "undef", &globalContext, &store);
|
||||
assertCalculationIs("28^7", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("3+√(2)→a", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Approximation, "√(2)+3", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("1/2", DisplayOutput::ExactAndApproximate, EqualSign::Equal, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("1/3", DisplayOutput::ExactAndApproximate, EqualSign::Approximation, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("1/0", DisplayOutput::ExactOnly, EqualSign::Unknown, "undef", "undef", "undef", &globalContext, &store);
|
||||
assertCalculationIs("2x-x", DisplayOutput::ExactOnly, EqualSign::Unknown, "x", "undef", "undef", &globalContext, &store);
|
||||
assertCalculationIs("[[1,2,3]]", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("[[1,x,3]]", DisplayOutput::ExactAndApproximate, EqualSign::Unknown, nullptr, "[[1,undef,3]]", "[[1,undef,3]]", &globalContext, &store);
|
||||
assertCalculationIs("28^7", DisplayOutput::ExactAndApproximate, EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("3+√(2)→a", DisplayOutput::ExactAndApproximate, EqualSign::Approximation, "√(2)+3", nullptr, nullptr, &globalContext, &store);
|
||||
Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy();
|
||||
assertCalculationIs("3+2→a", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Equal, "5", "5", "5", &globalContext, &store);
|
||||
assertCalculationIs("3+2→a", DisplayOutput::ApproximateOnly, EqualSign::Equal, "5", "5", "5", &globalContext, &store);
|
||||
Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy();
|
||||
assertCalculationIs("3→a", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Equal, "3", "3", "3", &globalContext, &store);
|
||||
assertCalculationIs("3→a", DisplayOutput::ApproximateOnly, EqualSign::Equal, "3", "3", "3", &globalContext, &store);
|
||||
Ion::Storage::sharedStorage()->recordNamed("a.exp").destroy();
|
||||
assertCalculationIs("3+x→f(x)", ::Calculation::Calculation::DisplayOutput::ExactOnly, ::Calculation::Calculation::EqualSign::Unknown, "x+3", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("3+x→f(x)", DisplayOutput::ExactOnly, EqualSign::Unknown, "x+3", nullptr, nullptr, &globalContext, &store);
|
||||
Ion::Storage::sharedStorage()->recordNamed("f.func").destroy();
|
||||
assertCalculationIs("1+1+random()", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("1+1+round(1.343,2)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "3.34", "3.34", &globalContext, &store);
|
||||
assertCalculationIs("randint(2,2)+3", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, "5", "5", "5", &globalContext, &store);
|
||||
assertCalculationIs("confidence(0.5,2)+3", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("prediction(0.5,2)+3", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("prediction95(0.5,2)+3", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("1+1+random()", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("1+1+round(1.343,2)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "3.34", "3.34", &globalContext, &store);
|
||||
assertCalculationIs("randint(2,2)+3", DisplayOutput::ApproximateOnly, EqualSign::Unknown, "5", "5", "5", &globalContext, &store);
|
||||
assertCalculationIs("confidence(0.5,2)+3", DisplayOutput::ExactOnly, EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("prediction(0.5,2)+3", DisplayOutput::ExactOnly, EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("prediction95(0.5,2)+3", DisplayOutput::ExactOnly, EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
|
||||
}
|
||||
|
||||
QUIZ_CASE(calculation_symbolic_computation) {
|
||||
Shared::GlobalContext globalContext;
|
||||
CalculationStore store;
|
||||
CalculationStore store(calculationBuffer,calculationBufferSize);
|
||||
|
||||
assertCalculationIs("x+x+1+3+√(π)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, "undef", "undef", "undef", &globalContext, &store);
|
||||
assertCalculationIs("f(x)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, "undef", "undef", "undef", &globalContext, &store);
|
||||
assertCalculationIs("1+x→f(x)", ::Calculation::Calculation::DisplayOutput::ExactOnly, ::Calculation::Calculation::EqualSign::Unknown, "x+1", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("f(x)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, "undef", "undef", "undef", &globalContext, &store);
|
||||
assertCalculationIs("f(2)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Equal, "3", "3", "3", &globalContext, &store);
|
||||
assertCalculationIs("2→x", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Equal, "2", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("f(x)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Equal, "3", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("x+x+1+3+√(π)", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Approximation, "√(π)+8", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("x+x+1+3+√(π)", DisplayOutput::ExactOnly, EqualSign::Unknown, "2×x+√(π)+4", "undef", "undef", &globalContext, &store);
|
||||
assertCalculationIs("f(x)", DisplayOutput::ExactOnly, EqualSign::Unknown, "f×x", "undef", "undef", &globalContext, &store);
|
||||
assertCalculationIs("1+x→f(x)", DisplayOutput::ExactOnly, EqualSign::Unknown, "x+1", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("f(x)", DisplayOutput::ExactOnly, EqualSign::Unknown, "x+1", "undef", "undef", &globalContext, &store);
|
||||
assertCalculationIs("f(2)", DisplayOutput::ApproximateOnly, EqualSign::Equal, "3", "3", "3", &globalContext, &store);
|
||||
assertCalculationIs("2→x", DisplayOutput::ApproximateOnly, EqualSign::Equal, "2", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("f(x)", DisplayOutput::ApproximateOnly, EqualSign::Equal, "3", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("x+x+1+3+√(π)", DisplayOutput::ExactAndApproximate, EqualSign::Approximation, "√(π)+8", nullptr, nullptr, &globalContext, &store);
|
||||
|
||||
Ion::Storage::sharedStorage()->recordNamed("f.func").destroy();
|
||||
Ion::Storage::sharedStorage()->recordNamed("x.exp").destroy();
|
||||
@@ -131,18 +155,18 @@ QUIZ_CASE(calculation_symbolic_computation) {
|
||||
|
||||
QUIZ_CASE(calculation_symbolic_computation_and_parametered_expressions) {
|
||||
Shared::GlobalContext globalContext;
|
||||
CalculationStore store;
|
||||
CalculationStore store(calculationBuffer,calculationBufferSize);
|
||||
|
||||
assertCalculationIs("int((ℯ^(-x))-x^(0.5), x, 0, 3)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store); // Tests a bug with symbolic computation
|
||||
assertCalculationIs("int(x,x,0,2)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "2", "2", &globalContext, &store);
|
||||
assertCalculationIs("sum(x,x,0,2)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "3", "3", &globalContext, &store);
|
||||
assertCalculationIs("product(x,x,1,2)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "2", "2", &globalContext, &store);
|
||||
assertCalculationIs("diff(x^2,x,3)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "6", "6", &globalContext, &store);
|
||||
assertCalculationIs("2→x", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("int(x,x,0,2)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "2", "2", &globalContext, &store);
|
||||
assertCalculationIs("sum(x,x,0,2)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "3", "3", &globalContext, &store);
|
||||
assertCalculationIs("product(x,x,1,2)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "2", "2", &globalContext, &store);
|
||||
assertCalculationIs("diff(x^2,x,3)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "6", "6", &globalContext, &store);
|
||||
assertCalculationIs("int((ℯ^(-x))-x^(0.5), x, 0, 3)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store); // Tests a bug with symbolic computation
|
||||
assertCalculationIs("int(x,x,0,2)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "2", "2", &globalContext, &store);
|
||||
assertCalculationIs("sum(x,x,0,2)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "3", "3", &globalContext, &store);
|
||||
assertCalculationIs("product(x,x,1,2)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "2", "2", &globalContext, &store);
|
||||
assertCalculationIs("diff(x^2,x,3)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "6", "6", &globalContext, &store);
|
||||
assertCalculationIs("2→x", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("int(x,x,0,2)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "2", "2", &globalContext, &store);
|
||||
assertCalculationIs("sum(x,x,0,2)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "3", "3", &globalContext, &store);
|
||||
assertCalculationIs("product(x,x,1,2)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "2", "2", &globalContext, &store);
|
||||
assertCalculationIs("diff(x^2,x,3)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "6", "6", &globalContext, &store);
|
||||
|
||||
Ion::Storage::sharedStorage()->recordNamed("x.exp").destroy();
|
||||
}
|
||||
@@ -150,34 +174,34 @@ QUIZ_CASE(calculation_symbolic_computation_and_parametered_expressions) {
|
||||
|
||||
QUIZ_CASE(calculation_complex_format) {
|
||||
Shared::GlobalContext globalContext;
|
||||
CalculationStore store;
|
||||
CalculationStore store(calculationBuffer,calculationBufferSize);
|
||||
|
||||
Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Real);
|
||||
assertCalculationIs("1+𝐢", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "1+𝐢", "1+𝐢", &globalContext, &store);
|
||||
assertCalculationIs("√(-1)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, "unreal", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("ln(-2)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "unreal", "unreal", &globalContext, &store);
|
||||
assertCalculationIs("√(-1)×√(-1)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "unreal", "unreal", &globalContext, &store);
|
||||
assertCalculationIs("(-8)^(1/3)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "-2", "-2", &globalContext, &store);
|
||||
assertCalculationIs("(-8)^(2/3)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "4", "4", &globalContext, &store);
|
||||
assertCalculationIs("(-2)^(1/4)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "unreal", "unreal", &globalContext, &store);
|
||||
assertCalculationIs("1+𝐢", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "1+𝐢", "1+𝐢", &globalContext, &store);
|
||||
assertCalculationIs("√(-1)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, "unreal", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("ln(-2)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "unreal", "unreal", &globalContext, &store);
|
||||
assertCalculationIs("√(-1)×√(-1)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "unreal", "unreal", &globalContext, &store);
|
||||
assertCalculationIs("(-8)^(1/3)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "-2", "-2", &globalContext, &store);
|
||||
assertCalculationIs("(-8)^(2/3)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "4", "4", &globalContext, &store);
|
||||
assertCalculationIs("(-2)^(1/4)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "unreal", "unreal", &globalContext, &store);
|
||||
|
||||
Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Cartesian);
|
||||
assertCalculationIs("1+𝐢", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "1+𝐢", "1+𝐢", &globalContext, &store);
|
||||
assertCalculationIs("√(-1)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "𝐢", "𝐢", &globalContext, &store);
|
||||
assertCalculationIs("ln(-2)", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Approximation, "ln(-2)", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("√(-1)×√(-1)", ::Calculation::Calculation::DisplayOutput::ApproximateOnly, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "-1", "-1", &globalContext, &store);
|
||||
assertCalculationIs("(-8)^(1/3)", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Approximation, "1+√(3)×𝐢", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("(-8)^(2/3)", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Approximation, "-2+2×√(3)×𝐢", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("(-2)^(1/4)", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Approximation, "root(8,4)/2+root(8,4)/2×𝐢", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("1+𝐢", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "1+𝐢", "1+𝐢", &globalContext, &store);
|
||||
assertCalculationIs("√(-1)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "𝐢", "𝐢", &globalContext, &store);
|
||||
assertCalculationIs("ln(-2)", DisplayOutput::ExactAndApproximate, EqualSign::Approximation, "ln(-2)", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("√(-1)×√(-1)", DisplayOutput::ApproximateOnly, EqualSign::Unknown, nullptr, "-1", "-1", &globalContext, &store);
|
||||
assertCalculationIs("(-8)^(1/3)", DisplayOutput::ExactAndApproximate, EqualSign::Approximation, "1+√(3)×𝐢", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("(-8)^(2/3)", DisplayOutput::ExactAndApproximate, EqualSign::Approximation, "-2+2×√(3)×𝐢", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("(-2)^(1/4)", DisplayOutput::ExactAndApproximate, EqualSign::Approximation, "root(8,4)/2+root(8,4)/2×𝐢", nullptr, nullptr, &globalContext, &store);
|
||||
|
||||
Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Polar);
|
||||
assertCalculationIs("1+𝐢", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Approximation, "√(2)×ℯ^\u0012π/4×𝐢\u0013", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("√(-1)", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Approximation, "ℯ^\u0012π/2×𝐢\u0013", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("ln(-2)", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Approximation, "ln(-2)", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("√(-1)×√(-1)", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Unknown, nullptr, "ℯ^\u00123.141593×𝐢\u0013", "ℯ^\u00123.1415926535898×𝐢\u0013", &globalContext, &store);
|
||||
assertCalculationIs("(-8)^(1/3)", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Approximation, "2×ℯ^\u0012π/3×𝐢\u0013", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("(-8)^(2/3)", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Approximation, "4×ℯ^\u0012\u00122×π\u0013/3×𝐢\u0013", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("(-2)^(1/4)", ::Calculation::Calculation::DisplayOutput::ExactAndApproximate, ::Calculation::Calculation::EqualSign::Approximation, "root(2,4)×ℯ^\u0012π/4×𝐢\u0013", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("1+𝐢", DisplayOutput::ExactAndApproximate, EqualSign::Approximation, "√(2)×ℯ^\u0012π/4×𝐢\u0013", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("√(-1)", DisplayOutput::ExactAndApproximate, EqualSign::Approximation, "ℯ^\u0012π/2×𝐢\u0013", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("ln(-2)", DisplayOutput::ExactAndApproximate, EqualSign::Approximation, "ln(-2)", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("√(-1)×√(-1)", DisplayOutput::ExactAndApproximate, EqualSign::Unknown, nullptr, "ℯ^\u00123.141593×𝐢\u0013", "ℯ^\u00123.1415926535898×𝐢\u0013", &globalContext, &store);
|
||||
assertCalculationIs("(-8)^(1/3)", DisplayOutput::ExactAndApproximate, EqualSign::Approximation, "2×ℯ^\u0012π/3×𝐢\u0013", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("(-8)^(2/3)", DisplayOutput::ExactAndApproximate, EqualSign::Approximation, "4×ℯ^\u0012\u00122×π\u0013/3×𝐢\u0013", nullptr, nullptr, &globalContext, &store);
|
||||
assertCalculationIs("(-2)^(1/4)", DisplayOutput::ExactAndApproximate, EqualSign::Approximation, "root(2,4)×ℯ^\u0012π/4×𝐢\u0013", nullptr, nullptr, &globalContext, &store);
|
||||
|
||||
Poincare::Preferences::sharedPreferences()->setComplexFormat(Poincare::Preferences::ComplexFormat::Cartesian);
|
||||
}
|
||||
|
||||
12
apps/clock_timer.cpp
Normal file
12
apps/clock_timer.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "clock_timer.h"
|
||||
#include "apps_container.h"
|
||||
|
||||
ClockTimer::ClockTimer(AppsContainer * container) :
|
||||
Timer(1),
|
||||
m_container(container)
|
||||
{
|
||||
}
|
||||
|
||||
bool ClockTimer::fire() {
|
||||
return m_container->updateClock();
|
||||
}
|
||||
16
apps/clock_timer.h
Normal file
16
apps/clock_timer.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef APPS_CLOCK_TIMER_H
|
||||
#define APPS_CLOCK_TIMER_H
|
||||
|
||||
#include <escher.h>
|
||||
|
||||
class AppsContainer;
|
||||
|
||||
class ClockTimer : public Timer {
|
||||
public:
|
||||
ClockTimer(AppsContainer * container);
|
||||
private:
|
||||
bool fire() override;
|
||||
AppsContainer * m_container;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,6 +1,8 @@
|
||||
apps += Code::App
|
||||
app_headers += apps/code/app.h
|
||||
|
||||
SFLAGS += -DHAS_CODE
|
||||
|
||||
app_code_src = $(addprefix apps/code/,\
|
||||
app.cpp \
|
||||
console_controller.cpp \
|
||||
@@ -15,6 +17,7 @@ app_code_src = $(addprefix apps/code/,\
|
||||
sandbox_controller.cpp \
|
||||
script_name_cell.cpp \
|
||||
script_parameter_controller.cpp \
|
||||
toolbox_ion_keys.cpp \
|
||||
)
|
||||
|
||||
app_code_test_src = $(addprefix apps/code/,\
|
||||
@@ -29,6 +32,7 @@ app_code_test_src = $(addprefix apps/code/,\
|
||||
|
||||
tests_src += $(addprefix apps/code/test/,\
|
||||
variable_box_controller.cpp\
|
||||
toolbox_ion_keys_dummy.cpp \
|
||||
)
|
||||
|
||||
app_code_src += $(app_code_test_src)
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
#include <apps/i18n.h>
|
||||
#include "helpers.h"
|
||||
#include <ion/unicode/utf8_helper.h>
|
||||
#include <apps/apps_container.h>
|
||||
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
extern "C" int calculator;
|
||||
extern "C" const int prizm_heap_size;
|
||||
extern "C" char prizm_heap[];
|
||||
#endif
|
||||
|
||||
namespace Code {
|
||||
|
||||
@@ -89,16 +96,18 @@ App::App(Snapshot * snapshot) :
|
||||
, snapshot->lockOnConsole()
|
||||
#endif
|
||||
),
|
||||
m_listFooter(&m_codeStackViewController, &m_menuController, &m_menuController, ButtonRowController::Position::Bottom, ButtonRowController::Style::EmbossedGrey, ButtonRowController::Size::Large),
|
||||
m_listFooter(&m_codeStackViewController, &m_menuController, &m_menuController, ButtonRowController::Position::Bottom, ButtonRowController::Style::EmbossedGray, ButtonRowController::Size::Large),
|
||||
m_menuController(&m_listFooter, this, snapshot->scriptStore(), &m_listFooter),
|
||||
m_codeStackViewController(&m_modalViewController, &m_listFooter),
|
||||
m_variableBoxController(snapshot->scriptStore())
|
||||
{
|
||||
Clipboard::sharedClipboard()->enterPython();
|
||||
}
|
||||
|
||||
App::~App() {
|
||||
assert(!m_consoleController.inputRunLoopActive());
|
||||
deinitPython();
|
||||
Clipboard::sharedClipboard()->exitPython();
|
||||
}
|
||||
|
||||
bool App::handleEvent(Ion::Events::Event event) {
|
||||
@@ -127,6 +136,16 @@ VariableBoxController * App::variableBoxForInputEventHandler(InputEventHandler *
|
||||
}
|
||||
|
||||
bool App::textInputDidReceiveEvent(InputEventHandler * textInput, Ion::Events::Event event) {
|
||||
if (event == Ion::Events::XNT) {
|
||||
int bufferSize = CodePoint::MaxCodePointCharLength + 1;
|
||||
char buffer[bufferSize];
|
||||
bool shouldRemoveLastCharacter = false;
|
||||
CodePoint codePoint = AppsContainer::sharedAppsContainer()->XNT('x', &shouldRemoveLastCharacter);
|
||||
UTF8Decoder::CodePointToChars(codePoint, buffer, bufferSize);
|
||||
buffer[UTF8Decoder::CharSizeOfCodePoint(codePoint)] = 0;
|
||||
textInput->handleEventWithText(const_cast<char *>(buffer), false, false, shouldRemoveLastCharacter);
|
||||
return true;
|
||||
}
|
||||
const char * pythonText = Helpers::PythonTextForEvent(event);
|
||||
if (pythonText != nullptr) {
|
||||
textInput->handleEventWithText(pythonText);
|
||||
@@ -137,7 +156,17 @@ bool App::textInputDidReceiveEvent(InputEventHandler * textInput, Ion::Events::E
|
||||
|
||||
void App::initPythonWithUser(const void * pythonUser) {
|
||||
if (!m_pythonUser) {
|
||||
MicroPython::init(m_pythonHeap, m_pythonHeap + k_pythonHeapSize);
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
if (calculator == 1) { // fxcg50
|
||||
MicroPython::init( (void *) 0x8c200000, (void *)(0x8c200000+ 0x2e0000));
|
||||
} else if (calculator >= 1 && calculator <=4 ) {
|
||||
MicroPython::init( prizm_heap, prizm_heap+prizm_heap_size);
|
||||
} else {
|
||||
#endif
|
||||
MicroPython::init(m_pythonHeap, m_pythonHeap + k_pythonHeapSize);
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
}
|
||||
#endif
|
||||
}
|
||||
m_pythonUser = pythonUser;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "script_store.h"
|
||||
#include "python_toolbox.h"
|
||||
#include "variable_box_controller.h"
|
||||
#include "../shared/shared_app.h"
|
||||
|
||||
namespace Code {
|
||||
|
||||
@@ -21,7 +22,7 @@ public:
|
||||
App::Descriptor::ExaminationLevel examinationLevel() override;
|
||||
const Image * icon() override;
|
||||
};
|
||||
class Snapshot : public ::App::Snapshot {
|
||||
class Snapshot : public SharedApp::Snapshot {
|
||||
public:
|
||||
Snapshot();
|
||||
App * unpack(Container * container) override;
|
||||
@@ -74,7 +75,7 @@ public:
|
||||
|
||||
VariableBoxController * variableBoxController() { return &m_variableBoxController; }
|
||||
|
||||
static constexpr int k_pythonHeapSize = 32768;
|
||||
static constexpr int k_pythonHeapSize = 69500;
|
||||
|
||||
private:
|
||||
/* Python delegate:
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
AddScript = "Skript hinzufügen"
|
||||
AllowedCharactersaz09 = "Erlaubte Zeichen: a-z, 0-9, _"
|
||||
Autocomplete = "Autovervollständigung"
|
||||
AutoImportScript = "Automatischer Import in Konsole"
|
||||
BuiltinsAndKeywords = "Native Funktionen und Schlüsselwörter"
|
||||
AutoImportScript = "Automatischer Import in die Konsole"
|
||||
BuiltinsAndKeywords = "Native Funktionen & Schlüsselwörter"
|
||||
Console = "Interaktive Konsole"
|
||||
DeleteScript = "Skript löschen"
|
||||
DuplicateScript = "Skript duplizieren"
|
||||
ExecuteScript = "Skript ausführen"
|
||||
FunctionsAndVariables = "Funktionen und Variablen"
|
||||
ImportedModulesAndScripts = "Importierte Module und Skripte"
|
||||
NoWordAvailableHere = "Kein Wort ist hier verfübar."
|
||||
ScriptInProgress = "Aktuelle Skript"
|
||||
NoWordAvailableHere = "Hier ist kein Wort verfügbar."
|
||||
ScriptInProgress = "Aktuelles Skript"
|
||||
ScriptOptions = "Skriptoptionen"
|
||||
ScriptSize = "Script size"
|
||||
ScriptSize = "Skriptgröße"
|
||||
|
||||
@@ -12,4 +12,4 @@ ImportedModulesAndScripts = "Módulos y archivos importados"
|
||||
NoWordAvailableHere = "No hay ninguna palabra disponible aquí."
|
||||
ScriptInProgress = "Archivo en curso"
|
||||
ScriptOptions = "Opciones del archivo"
|
||||
ScriptSize = "Script size"
|
||||
ScriptSize = "Tamaño del script"
|
||||
|
||||
@@ -12,4 +12,4 @@ ImportedModulesAndScripts = "Modules et scripts importés"
|
||||
NoWordAvailableHere = "Aucun mot disponible à cet endroit."
|
||||
ScriptInProgress = "Script en cours"
|
||||
ScriptOptions = "Options de script"
|
||||
ScriptSize = "Script size"
|
||||
ScriptSize = "Taille du script"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
AddScript = "Script hozzadáadása"
|
||||
AddScript = "Script hozzáadása"
|
||||
AllowedCharactersaz09 = "Engedélyezett karakterek: a-z, 0-9, _"
|
||||
Autocomplete = "Autocomplete"
|
||||
Autocomplete = "Önkiegészítés"
|
||||
AutoImportScript = "Script automata importálása"
|
||||
BuiltinsAndKeywords = "Builtins and keywords"
|
||||
BuiltinsAndKeywords = "Beépített fonkciók és szókincs"
|
||||
Console = "Konzol"
|
||||
DeleteScript = "Script törlése"
|
||||
DuplicateScript = "Script másolása"
|
||||
ExecuteScript = "Script indítása"
|
||||
FunctionsAndVariables = "Függvények és változók"
|
||||
ImportedModulesAndScripts = "Imported modules and scripts"
|
||||
NoWordAvailableHere = "No word available here."
|
||||
ScriptInProgress = "Script in progress"
|
||||
FunctionsAndVariables = "Fonktiók és változók"
|
||||
ImportedModulesAndScripts = "Importált scriptek és modulok"
|
||||
NoWordAvailableHere = "Nincs rendelkezésre álló szó."
|
||||
ScriptInProgress = "Script müködésben"
|
||||
ScriptOptions = "Script beállítások"
|
||||
ScriptSize = "Script size"
|
||||
ScriptSize = "Script mérete"
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
CodeAppCapital = "PYTHON"
|
||||
ConsolePrompt = ">>> "
|
||||
ScriptParameters = "..."
|
||||
|
||||
@@ -1,222 +1,265 @@
|
||||
PythonPound = "Kommentar"
|
||||
PythonPercent = "Modulo"
|
||||
PythonColon = "Doppelpunkt"
|
||||
PythonSemicon = "Semikolon"
|
||||
PythonExclamationMark = "Ausrufezeichen"
|
||||
PythonLessThan = "Kleiner als"
|
||||
PythonGreaterThan = "Größer als"
|
||||
PythonQuestionMark = "Fragezeichen"
|
||||
Python1J = "Imaginäres i"
|
||||
PythonLF = "Zeilenvorschub"
|
||||
PythonTab = "Tabulator"
|
||||
PythonAmpersand = "Bitweise und"
|
||||
PythonSymbolExp = "Bitweise exklusiv oder"
|
||||
PythonVerticalBar = "Bitweise oder"
|
||||
PythonAmpersand = "Bitweises und"
|
||||
PythonSymbolExp = "Bitweises exklusives oder"
|
||||
PythonVerticalBar = "Bitweises oder"
|
||||
PythonImag = "Imaginärteil von z"
|
||||
PythonReal = "Realteil von z"
|
||||
PythonSingleQuote = "Einfaches Anführungszeichen"
|
||||
PythonAbs = "Absolute/r Wert/Größe"
|
||||
PythonAcos = "Arkuskosinus"
|
||||
PythonAcosh = "Hyperbelkosinus"
|
||||
PythonAppend = "Hängt x an das Ende der Liste"
|
||||
PythonArrow = "Arrow from (x,y) to (x+dx,y+dy)"
|
||||
PythonAsin = "Arkussinus"
|
||||
PythonAsinh = "Hyperbelsinus"
|
||||
PythonAbs = "Absoluter Wert/Absolute Größe"
|
||||
PythonAcos = "Bogenkosinus"
|
||||
PythonAcosh = "Bogenhyperbolischer Kosinus"
|
||||
PythonAppend = "x an das Ende der Liste anfügen"
|
||||
PythonArrow = "Pfeil von (x,y) nach (x+dx,y+dy)"
|
||||
PythonAsin = "Sinusbogen"
|
||||
PythonAsinh = "Kreisbogen hyperbolischer Sinus"
|
||||
PythonAtan = "Arkustangens"
|
||||
PythonAtan2 = "Gib atan(y/x)"
|
||||
PythonAtan2 = "Rückgabe atan(y/x)"
|
||||
PythonAtanh = "Hyperbeltangens"
|
||||
PythonAxis = "Set axes to (xmin,xmax,ymin,ymax)"
|
||||
PythonBar = "Draw a bar plot with x values"
|
||||
PythonBin = "Ganzzahl nach binär konvertieren"
|
||||
PythonCeil = "Aufrundung"
|
||||
PythonChoice = "Zufallszahl aus der Liste"
|
||||
PythonClear = "Leere die Liste"
|
||||
PythonAxis = "Achsen auf (xmin,xmax,ymin,ymax)"
|
||||
PythonBar = "Balkendiagramm mit x-Werten"
|
||||
PythonBin = "Ganzzahl in Binärwert umwandeln"
|
||||
PythonCeil = "Aufrunden"
|
||||
PythonChoice = "Zufällige Zahl in der Liste"
|
||||
PythonClear = "Liste leeren"
|
||||
PythonCmathFunction = "cmath-Modul-Funktionspräfix"
|
||||
PythonColor = "Definiere eine RGB-Farbe"
|
||||
PythonColorBlack = "Black color"
|
||||
PythonColorBlue = "Blue color"
|
||||
PythonColorBrown = "Brown color"
|
||||
PythonColorGreen = "Green color"
|
||||
PythonColorGrey = "Grey color"
|
||||
PythonColorOrange = "Orange color"
|
||||
PythonColorPink = "Pink color"
|
||||
PythonColorPurple = "Purple color"
|
||||
PythonColorRed = "Red color"
|
||||
PythonColorWhite = "White color"
|
||||
PythonColorYellow = "Yellow color"
|
||||
PythonComplex = "a+ib zurückgeben"
|
||||
PythonCopySign = "x mit dem Vorzeichen von y"
|
||||
PythonColor = "Eine RGB-Farbe definieren"
|
||||
PythonColorBlack = "Farbe Schwarz"
|
||||
PythonColorBlue = "Farbe Blau"
|
||||
PythonColorBrown = "Farbe Braun"
|
||||
PythonColorGray = "Farbe Grau"
|
||||
PythonColorGreen = "Farbe Grün"
|
||||
PythonColorOrange = "Farbe Orange"
|
||||
PythonColorPink = "Farbe Rosa"
|
||||
PythonColorPurple = "Farbe Violett"
|
||||
PythonColorRed = "Farbe Rot"
|
||||
PythonColorWhite = "Farbe Weiß"
|
||||
PythonColorYellow = "Farbe Gelb"
|
||||
PythonComplex = "Gib a+ib zurück"
|
||||
PythonCopySign = "Gib x mit Vorzeichen von y zurück"
|
||||
PythonCos = "Kosinus"
|
||||
PythonCosh = "Hyperbolic cosine"
|
||||
PythonCount = "Zählt wie oft x vorkommt"
|
||||
PythonDegrees = "x von Radian zu Grad umwandeln"
|
||||
PythonCosh = "Hyperbolischer Kosinus"
|
||||
PythonCount = "Zählt die Vorkommen von x"
|
||||
PythonDegrees = "x von Bogenmaß in Grad umrechnen"
|
||||
PythonDivMod = "Quotient und Rest"
|
||||
PythonDrawString = "Schreibt Text bei (x,y)"
|
||||
PythonDrawCircle = "Zeichne einen Kreis"
|
||||
PythonDrawLine = "Eine Linie zeichnen"
|
||||
PythonDrawString = "Text bei Pixel (x,y) darstellen"
|
||||
PythonErf = "Fehlerfunktion"
|
||||
PythonErfc = "Complementary error function"
|
||||
PythonEval = "Return the evaluated expression"
|
||||
PythonErfc = "Komplementäre Fehlerfunktion"
|
||||
PythonEval = "Rückgabe ausgewerteter Ausdruck"
|
||||
PythonExp = "Exponentialfunktion"
|
||||
PythonExpm1 = "Berechne exp(x)-1"
|
||||
PythonFactorial = "Fakultät von x"
|
||||
PythonFabs = "Absoluter Wert"
|
||||
PythonFillRect = "Malt ein Rechteck bei Pixel (x,y)"
|
||||
PythonFloat = "Wandelt x zu float um"
|
||||
PythonFloor = "Floor"
|
||||
PythonFillRect = "Gefülltes Rechteck bei Pixel (x,y)"
|
||||
PythonFillCircle = "Füllt einen Kreis"
|
||||
PythonFillPolygon = "Füllt ein Polygon"
|
||||
PythonFloat = "x in einen Fließkommawert umwandeln"
|
||||
PythonFloor = "Abrunden"
|
||||
PythonFmod = "a modulo b"
|
||||
PythonFrExp = "Mantissa and exponent of x: (m,e)"
|
||||
PythonGamma = "Gamma function"
|
||||
PythonGetPixel = "Return pixel (x,y) color"
|
||||
PythonGetrandbits = "Integer with k random bits"
|
||||
PythonGrid = "Toggle the visibility of the grid"
|
||||
PythonHex = "Ganzzahl zu Hexadecimal"
|
||||
PythonHist = "Draw the histogram of x"
|
||||
PythonImportCmath = "cmath Modul importieren"
|
||||
PythonImportIon = "ion Modul importieren"
|
||||
PythonImportKandinsky = "kandinsky Modul importieren"
|
||||
PythonImportRandom = "random Modul importieren"
|
||||
PythonImportMath = "math Modul importieren"
|
||||
PythonImportMatplotlibPyplot = "Import matplotlib.pyplot module"
|
||||
PythonImportOs = "os Modul importieren"
|
||||
PythonOsUname = "Informieren Sie sich über das System"
|
||||
PythonFrExp = "Mantisse und Exponent von x: (m,e)"
|
||||
PythonGamma = "Gamma-Funktion"
|
||||
PythonGetKeys = "Gedrückte Tasten erhalten"
|
||||
PythonGetPalette = "Themenpalette erhalten"
|
||||
PythonGetPixel = "Farbe von Pixel (x,y) zurückgeben"
|
||||
PythonGetrandbits = "Ganzzahl mit k Zufallsbits"
|
||||
PythonGrid = "Sichtbarkeit des Gitters umschalten"
|
||||
PythonHex = "Ganzzahl in Hexadezimal umwandeln"
|
||||
PythonHist = "Zeichnet das Histogramm von x"
|
||||
PythonImportCmath = "cmath-Modul importieren"
|
||||
PythonImportIon = "Ion-Modul importieren"
|
||||
PythonImportKandinsky = "Kandinsky-Modul importieren"
|
||||
PythonImportRandom = "Random-Modul importieren"
|
||||
PythonImportMath = "Math-Modul importieren"
|
||||
PythonImportMatplotlibPyplot = "Matplotlib.pyplot-Modul importieren"
|
||||
PythonImportNumpy = "Ulab.numpy-Modul importieren"
|
||||
PythonImportScipy = "Ulab.scipy-Modul importieren"
|
||||
PythonImportOs = "OS-Modul importieren"
|
||||
PythonImportSys = "SYS-Modul importieren"
|
||||
PythonOsUname = "Informationen über das System holen"
|
||||
PythonOsGetlogin = "Benutzernamen holen"
|
||||
PythonOsRemove = "Datei namens Dateiname entfernen"
|
||||
PythonOsRename = "Datei mit altem Namen in neuen Namen umbenennen"
|
||||
PythonOsRename = "Datei umbenennen von Alt nach Neu"
|
||||
PythonOsListdir = "Dateien im Speicher auflisten"
|
||||
PythonImportTime = "time Modul importieren"
|
||||
PythonImportTurtle = "turtle Modul importieren"
|
||||
PythonIndex = "Index, bei dem x zuerst vorkommt"
|
||||
PythonInput = "Eingabeaufforderung"
|
||||
PythonInsert = "x bei index i in der Liste einsetzen"
|
||||
PythonInt = "x zu Ganzzahl"
|
||||
PythonIonFunction = "ion module function prefix"
|
||||
PythonIsFinite = "Prüft ob x endlich ist"
|
||||
PythonIsInfinite = "Prüft ob x unendlich ist"
|
||||
PythonIsNaN = "Prüft ob x NaN ist"
|
||||
PythonIsKeyDown = "true wenn k gedrückt ist"
|
||||
PythonKandinskyFunction = "kandinsky module function prefix"
|
||||
PythonKeyLeft = "Linke Pfeiltaste"
|
||||
PythonKeyUp = "Pfeiltaste nach oben"
|
||||
PythonKeyDown = "Pfeiltaste nach unten"
|
||||
PythonKeyRight = "Rechte Pfeiltaste"
|
||||
PythonKeyOk = "OK Taste"
|
||||
PythonKeyBack = "ZURÜCK Taste"
|
||||
PythonKeyHome = "HOME Taste"
|
||||
PythonKeyOnOff = "AN/AUS Taste"
|
||||
PythonKeyShift = "SHIFT Taste"
|
||||
PythonKeyAlpha = "ALPHA Taste"
|
||||
PythonKeyXnt = "X,N,T Taste"
|
||||
PythonKeyVar = "VAR Taste"
|
||||
PythonKeyToolbox = "WERKZEUGBOX Taste"
|
||||
PythonKeyBackspace = "LÖSCHEN Taste"
|
||||
PythonKeyExp = "EXPONENTIAL Taste"
|
||||
PythonKeyLn = "NATURAL LOGARITHM Taste"
|
||||
PythonKeyLog = "DECIMAL LOGARITHM Taste"
|
||||
PythonKeyImaginary = "IMAGINÄRES I Taste"
|
||||
PythonKeyComma = "KOMMA Taste"
|
||||
PythonKeyPower = "HOCH Taste"
|
||||
PythonKeySine = "SINUS Taste"
|
||||
PythonKeyCosine = "COSINUS Taste"
|
||||
PythonKeyTangent = "TANGENZ Taste"
|
||||
PythonKeyPi = "PI Taste"
|
||||
PythonKeySqrt = "WURZEL Taste"
|
||||
PythonKeySquare = "QUADRAT Taste"
|
||||
PythonKeySeven = "7 Taste"
|
||||
PythonKeyEight = "8 Taste"
|
||||
PythonKeyNine = "9 Taste"
|
||||
PythonSysExit = "Terminate current program"
|
||||
PythonSysPrintexception = "Print exception"
|
||||
PythonSysByteorder = "The byte order of the system"
|
||||
PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
PythonImportTime = "Time-Modul importieren"
|
||||
PythonImportTurtle = "Turtle-Modul importieren"
|
||||
PythonIndex = "Index des ersten x-Vorkommens"
|
||||
PythonInput = "Einen Wert abfragen"
|
||||
PythonInsert = "x an Index i in die Liste einfügen"
|
||||
PythonInt = "x in eine ganze Zahl umwandeln"
|
||||
PythonIonFunction = "Ion-Modul-Funktionspräfix"
|
||||
PythonIsFinite = "Prüfen, ob x endlich ist"
|
||||
PythonIsInfinite = "Prüfen, ob x unendlich ist"
|
||||
PythonIsNaN = "Prüfen, ob x keine Zahl ist"
|
||||
PythonIsKeyDown = "Wahr, wenn die Taste k gedrückt ist"
|
||||
PythonBattery = "Rückgabe der Batteriespannung"
|
||||
PythonBatteryLevel = "Gibt den Batteriestand zurück"
|
||||
PythonBatteryIscharging = "Gibt zurück, ob die Batterie geladen wird"
|
||||
PythonSetBrightness = "Helligkeitsstufe festlegen"
|
||||
PythonGetBrightness = "Helligkeitsstufe abrufen"
|
||||
PythonKandinskyFunction = "Kandinsky-Modul Funktionspräfix"
|
||||
PythonKeyLeft = "LEFT ARROW key"
|
||||
PythonKeyUp = "UP ARROW key"
|
||||
PythonKeyDown = "DOWN ARROW key"
|
||||
PythonKeyRight = "RIGHT ARROW key"
|
||||
PythonKeyOk = "OK key"
|
||||
PythonKeyBack = "BACK key"
|
||||
PythonKeyHome = "HOME key"
|
||||
PythonKeyOnOff = "ON/OFF key"
|
||||
PythonKeyShift = "SHIFT key"
|
||||
PythonKeyAlpha = "ALPHA key"
|
||||
PythonKeyXnt = "X,N,T key"
|
||||
PythonKeyVar = "VAR key"
|
||||
PythonKeyToolbox = "TOOLBOX key"
|
||||
PythonKeyBackspace = "BACKSPACE key"
|
||||
PythonKeyExp = "EXPONENTIAL key"
|
||||
PythonKeyLn = "NATURAL LOGARITHM key"
|
||||
PythonKeyLog = "DECIMAL LOGARITHM key"
|
||||
PythonKeyImaginary = "IMAGINARY I key"
|
||||
PythonKeyComma = "COMMA key"
|
||||
PythonKeyPower = "POWER key"
|
||||
PythonKeySine = "SINE key"
|
||||
PythonKeyCosine = "COSINE key"
|
||||
PythonKeyTangent = "TANGENT key"
|
||||
PythonKeyPi = "PI key"
|
||||
PythonKeySqrt = "SQUARE ROOT key"
|
||||
PythonKeySquare = "SQUARE key"
|
||||
PythonKeySeven = "7 key"
|
||||
PythonKeyEight = "8 key"
|
||||
PythonKeyNine = "9 key"
|
||||
PythonKeyLeftParenthesis = "LEFT PARENTHESIS key"
|
||||
PythonKeyRightParenthesis = "RIGHT PARENTHESIS key"
|
||||
PythonKeyFour = "4 Taste"
|
||||
PythonKeyFive = "5 Taste"
|
||||
PythonKeySix = "6 Taste"
|
||||
PythonKeyMultiplication = "MULTIPLIKATIONSTASTE"
|
||||
PythonKeyDivision = "DIVISIONSTASTE"
|
||||
PythonKeyOne = "1 Taste"
|
||||
PythonKeyTwo = "2 Taste"
|
||||
PythonKeyThree = "3 Taste"
|
||||
PythonKeyPlus = "PLUS Taste"
|
||||
PythonKeyMinus = "MINUS Taste"
|
||||
PythonKeyZero = "0 Taste"
|
||||
PythonKeyDot = "PUNKT Taste"
|
||||
PythonKeyEe = "10 HOCH X Taste"
|
||||
PythonKeyAns = "ANS Taste"
|
||||
PythonKeyExe = "EXE Taste"
|
||||
PythonLdexp = "Return x*(2**i), inverse of frexp"
|
||||
PythonLength = "Length of an object"
|
||||
PythonLgamma = "Log-gamma function"
|
||||
PythonLog = "Logarithm to base a"
|
||||
PythonLog10 = "Logarithm to base 10"
|
||||
PythonLog2 = "Logarithm to base 2"
|
||||
PythonMathFunction = "math module function prefix"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot module prefix"
|
||||
PythonKeyFour = "4 key"
|
||||
PythonKeyFive = "5 key"
|
||||
PythonKeySix = "6 key"
|
||||
PythonKeyMultiplication = "MULTIPLICATION key"
|
||||
PythonKeyDivision = "DIVISION key"
|
||||
PythonKeyOne = "1 key"
|
||||
PythonKeyTwo = "2 key"
|
||||
PythonKeyThree = "3 key"
|
||||
PythonKeyPlus = "PLUS key"
|
||||
PythonKeyMinus = "MINUS key"
|
||||
PythonKeyZero = "0 key"
|
||||
PythonKeyDot = "DOT key"
|
||||
PythonKeyEe = "10 POWER X key"
|
||||
PythonKeyAns = "ANS key"
|
||||
PythonKeyExe = "EXE key"
|
||||
PythonLdexp = "Liefert x*(2**i), Inverse von frexp"
|
||||
PythonLength = "Länge eines Objekts"
|
||||
PythonLgamma = "Log-Gamma-Funktion"
|
||||
PythonLog = "Logarithmus zur Basis a"
|
||||
PythonLog10 = "Logarithmus zur Basis 10"
|
||||
PythonLog2 = "Logarithmus zur Basis 2"
|
||||
PythonMathFunction = "Funktionspräfix des Math-Moduls"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot Modul-Präfix"
|
||||
PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "Fractional and integer parts of x"
|
||||
PythonMonotonic = "Value of a monotonic clock"
|
||||
PythonOct = "Convert integer to octal"
|
||||
PythonPhase = "Phase of z"
|
||||
PythonPlot = "Plot y versus x as lines"
|
||||
PythonPolar = "z in polar coordinates"
|
||||
PythonPop = "Remove and return the last item"
|
||||
PythonPower = "x raised to the power y"
|
||||
PythonPrint = "Print object"
|
||||
PythonRadians = "Convert x from degrees to radians"
|
||||
PythonRandint = "Random integer in [a,b]"
|
||||
PythonRandom = "Floating point number in [0,1["
|
||||
PythonRandomFunction = "random module function prefix"
|
||||
PythonRandrange = "Random number in range(start,stop)"
|
||||
PythonRangeStartStop = "List from start to stop-1"
|
||||
PythonRangeStop = "List from 0 to stop-1"
|
||||
PythonRect = "Convert to cartesian coordinates"
|
||||
PythonRemove = "Remove the first occurrence of x"
|
||||
PythonReverse = "Reverse the elements of the list"
|
||||
PythonRound = "Round to n digits"
|
||||
PythonScatter = "Draw a scatter plot of y versus x"
|
||||
PythonSeed = "Initialize random number generator"
|
||||
PythonSetPixel = "Color pixel (x,y)"
|
||||
PythonShow = "Display the figure"
|
||||
PythonSin = "Sine"
|
||||
PythonSinh = "Hyperbolic sine"
|
||||
PythonSleep = "Suspend the execution for t seconds"
|
||||
PythonSort = "Sort the list"
|
||||
PythonSqrt = "Wurzel"
|
||||
PythonSum = "Sum the items of a list"
|
||||
PythonModf = "Bruch- und Ganzzahl-Anteile von x"
|
||||
PythonMonotonic = "Wert einer monotonen Uhr"
|
||||
PythonNumpyFunction = "numpy Modul-Präfix"
|
||||
PythonNumpyFftFunction = "numpy.fft Modul-Präfix"
|
||||
PythonNumpyLinalgFunction = "numpy.linalg Modul-Präfix"
|
||||
PythonScipyFunction = "scipy Modul-Präfix"
|
||||
PythonScipyLinalgFunction = "scipy.linalg Modul-Präfix"
|
||||
PythonScipyOptimizeFunction = "scipy.optimize Modul-Präfix"
|
||||
PythonScipySignalFunction = "scipy.signal Modul-Präfix"
|
||||
PythonScipySpecialFunction = "scipy.special Modul-Präfix"
|
||||
PythonOct = "Ganzzahl in Oktal umwandeln"
|
||||
PythonPhase = "Phase von z"
|
||||
PythonPlot = "Plotten von y gegen x als Linien"
|
||||
PythonPolar = "z in Polarkoordinaten"
|
||||
PythonPop = "Letztes Element abnehmen"
|
||||
PythonPower = "x erhöht mit der Potenz y"
|
||||
PythonPrint = "Objekt drucken"
|
||||
PythonRadians = "x von Grad in Bogenmaß umrechnen"
|
||||
PythonRandint = "Zufällige Ganzzahl in [a,b]"
|
||||
PythonRandom = "Fließkommazahl in [0,1]"
|
||||
PythonRandomFunction = "Random-Modul Funktionspräfix"
|
||||
PythonRandrange = "Zufallszahl im Bereich(start,stop)"
|
||||
PythonRangeStartStop = "Liste von Start bis Stop-1"
|
||||
PythonRangeStop = "Liste von 0 bis Stop-1"
|
||||
PythonRect = "In kartesische Koordinaten"
|
||||
PythonRemove = "Entferne das erste Vorkommen von x"
|
||||
PythonReverse = "Kehrt die Elemente der Liste um"
|
||||
PythonRound = "Runden auf n Stellen"
|
||||
PythonScatter = "Streudiagramm von y gg. x zeichnen"
|
||||
PythonSeed = "Zufallszahlengenerator initiieren"
|
||||
PythonSetPixel = "Pixel (x,y) einfärben"
|
||||
PythonShow = "Figur anzeigen"
|
||||
PythonSin = "Sinus"
|
||||
PythonSinh = "Hyperbolischer Sinus"
|
||||
PythonSleep = "Ausführung aussetzen für t Sekunden"
|
||||
PythonLocalTime = "Zeit in Tupel umwandeln"
|
||||
PythonMktime = "Tupel in Zeit umwandeln"
|
||||
PythonTime = "Abrufen des aktuellen Zeitstempels"
|
||||
PythonSetLocaltime = "Zeit aus einem Tupel einstellen"
|
||||
PythonRTCmode = "Aktuellen RTC-Modus abrufen"
|
||||
PythonSetRTCmode = "RTC-Modus festlegen"
|
||||
PythonSort = "Die Liste sortieren"
|
||||
PythonSqrt = "Quadratwurzel"
|
||||
PythonSum = "Summe der Elemente einer Liste"
|
||||
PythonTan = "Tangens"
|
||||
PythonTanh = "Hyperbolic tangent"
|
||||
PythonText = "Display a text at (x,y) coordinates"
|
||||
PythonTimeFunction = "time module function prefix"
|
||||
PythonTrunc = "x truncated to an integer"
|
||||
PythonTurtleBackward = "Move backward by x pixels"
|
||||
PythonTurtleCircle = "Circle of radius r pixels"
|
||||
PythonTurtleColor = "Stiftfarbe setzen"
|
||||
PythonTurtleColorMode = "Set the color mode to 1.0 or 255"
|
||||
PythonTurtleForward = "Move forward by x pixels"
|
||||
PythonTurtleFunction = "turtle module function prefix"
|
||||
PythonTurtleGoto = "Move to (x,y) coordinates"
|
||||
PythonTurtleHeading = "Return the current heading"
|
||||
PythonTurtleHideturtle = "Hide the turtle"
|
||||
PythonTurtleIsdown = "Return True if the pen is down"
|
||||
PythonTurtleLeft = "Turn left by a degrees"
|
||||
PythonTurtlePendown = "Pull the pen down"
|
||||
PythonTurtlePensize = "Set the line thickness to x pixels"
|
||||
PythonTurtlePenup = "Pull the pen up"
|
||||
PythonTurtlePosition = "Return the current (x,y) location"
|
||||
PythonTurtleReset = "Reset the drawing"
|
||||
PythonTurtleRight = "Turn right by a degrees"
|
||||
PythonTurtleSetheading = "Set the orientation to a degrees"
|
||||
PythonTurtleSetposition = "Positionne la tortue"
|
||||
PythonTurtleShowturtle = "Show the turtle"
|
||||
PythonTurtleSpeed = "Drawing speed between 0 and 10"
|
||||
PythonTurtleWrite = "Display a text"
|
||||
PythonUniform = "Floating point number in [a,b]"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Wait for n second"
|
||||
PythonMonotonic = "Return monotonic time"
|
||||
PythonTanh = "Hyperbolischer Tangens"
|
||||
PythonText = "Text an (x,y) Koordinaten anzeigen"
|
||||
PythonTimeFunction = "Time-Modul-Funktionspräfix"
|
||||
PythonTrunc = "x abgeschnitten auf eine ganze Zahl"
|
||||
PythonTurtleBackward = "Um x Pixel rückwärts bewegen"
|
||||
PythonTurtleCircle = "Kreis mit Radius r Pixel"
|
||||
PythonTurtleColor = "Setzt die Stiftfarbe"
|
||||
PythonTurtleColorMode = "Setzt Farbmodus auf 1.0 oder 255"
|
||||
PythonTurtleForward = "Um x Pixel vorwärts bewegen"
|
||||
PythonTurtleFunction = "Turtle-Modul-Funktionspräfix"
|
||||
PythonTurtleGoto = "Bewegen zu (x,y) Koordinaten"
|
||||
PythonTurtleHeading = "Liefert den aktuellen Kurs"
|
||||
PythonTurtleHideturtle = "Versteckt den Igel"
|
||||
PythonTurtleIsdown = "Wahr, wenn der Stift unten ist"
|
||||
PythonTurtleLeft = "Nach links um ein Grad drehen"
|
||||
PythonTurtlePendown = "Den Stift nach unten ziehen"
|
||||
PythonTurtlePensize = "Linienstärke auf x Pixel setzen"
|
||||
PythonTurtlePenup = "Den Stift nach oben ziehen"
|
||||
PythonTurtlePosition = "Aktuelle (x,y) Position zurückgeben"
|
||||
PythonTurtleReset = "Die Zeichnung zurücksetzen"
|
||||
PythonTurtleRight = "Um ein Grad nach rechts drehen"
|
||||
PythonTurtleSetheading = "Ausrichtung auf einen Grad setzen"
|
||||
PythonTurtleShowturtle = "Den Igel anzeigen"
|
||||
PythonTurtleSpeed = "Zeichengeschwindigkeit von 0 bis 10"
|
||||
PythonTurtleWrite = "Einen Text anzeigen"
|
||||
PythonUniform = "Fließkommazahl in [a,b]"
|
||||
PythonImportTime = "Time-Modul importieren"
|
||||
PythonMonotonic = "Monotone Zeit zurückgeben"
|
||||
PythonFileOpen = "Öffnet eine Datei"
|
||||
PythonFileSeekable = "Ist eine Datei durchsuchbar?"
|
||||
PythonFileSeek = "Dateicursor verschieben"
|
||||
PythonFileTell = "Cursorposition der Datei abrufen"
|
||||
PythonFileSeekable = "Kann Datei durchsucht werden?"
|
||||
PythonFileSeek = "Bewegt den Cursor einer Datei"
|
||||
PythonFileTell = "Position des Cursors ermitteln"
|
||||
PythonFileClose = "Schließt eine Datei"
|
||||
PythonFileClosed = "Wenn Datei geschlossen wurde"
|
||||
PythonFileRead = "Bis zu size Bytes lesen"
|
||||
PythonFileWrite = "Schreibe b in die Datei"
|
||||
PythonFileReadline = "Lies eine Zeile"
|
||||
PythonFileClosed = "Wahr, wenn Datei geschlossen wurde"
|
||||
PythonFileRead = "Lesen bis zu einer Größe von Bytes"
|
||||
PythonFileWrite = "Schreibe b in Datei"
|
||||
PythonFileReadline = "Liest Zeile oder Anzahl Bytes"
|
||||
PythonFileReadlines = "Liest eine Liste von Zeilen"
|
||||
PythonFileTruncate = "Größe der Datei ändern"
|
||||
PythonFileTruncate = "Verkleinert die Datei auf Größe"
|
||||
PythonFileWritelines = "Schreibt eine Liste von Zeilen"
|
||||
PythonFileName = "Dateiname"
|
||||
PythonFileMode = "Dateiöffnungsmodus"
|
||||
PythonFileReadable = "Ist die Datei lesbar?"
|
||||
PythonFileWritable = "Ist die Datei beschreibbar?"
|
||||
PythonFileName = "Enthält den Namen der Datei"
|
||||
PythonFileMode = "Enthält den Öffnungsmodus der Datei"
|
||||
PythonFileReadable = "Kann Datei gelesen werden?"
|
||||
PythonFileWritable = "Kann Datei geschrieben werden?"
|
||||
PythonImportUtils = "Importieren von ulab.utils"
|
||||
PythonUtilsFunction = "Funktionspräfix des utils-Moduls"
|
||||
PythonTurtleBgcolor = "Ändern Sie die Hintergrundfarbe"
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
PythonPound = "Comment"
|
||||
PythonPercent = "Modulo"
|
||||
PythonColon = "Colon"
|
||||
PythonSemicon = "Semicolon"
|
||||
PythonExclamationMark = "Exclamation mark"
|
||||
PythonLessThan = "Less than"
|
||||
PythonGreaterThan = "Greater than"
|
||||
PythonQuestionMark = "Question mark"
|
||||
Python1J = "Imaginary i"
|
||||
PythonLF = "line feed"
|
||||
PythonLF = "Line feed"
|
||||
PythonTab = "Tabulation"
|
||||
PythonAmpersand = "Bitwise and"
|
||||
PythonSymbolExp = "Bitwise exclusive or"
|
||||
@@ -30,8 +36,8 @@ PythonColor = "Define a rgb color"
|
||||
PythonColorBlack = "Black color"
|
||||
PythonColorBlue = "Blue color"
|
||||
PythonColorBrown = "Brown color"
|
||||
PythonColorGray = "Gray color"
|
||||
PythonColorGreen = "Green color"
|
||||
PythonColorGrey = "Grey color"
|
||||
PythonColorOrange = "Orange color"
|
||||
PythonColorPink = "Pink color"
|
||||
PythonColorPurple = "Purple color"
|
||||
@@ -45,19 +51,26 @@ PythonCosh = "Hyperbolic cosine"
|
||||
PythonCount = "Count the occurrences of x"
|
||||
PythonDegrees = "Convert x from radians to degrees"
|
||||
PythonDivMod = "Quotient and remainder"
|
||||
PythonDrawCircle = "Draw a circle"
|
||||
PythonDrawLine = "Draw a line"
|
||||
PythonDrawString = "Display a text from pixel (x,y)"
|
||||
PythonErf = "Error function"
|
||||
PythonErfc = "Complementary error function"
|
||||
PythonEval = "Return the evaluated expression"
|
||||
PythonExp = "Exponential function"
|
||||
PythonExpm1 = "Compute exp(x)-1"
|
||||
PythonFactorial = "Factorial of x"
|
||||
PythonFabs = "Absolute value"
|
||||
PythonFillCircle = "Fill a circle"
|
||||
PythonFillPolygon = "Fill a polygon"
|
||||
PythonFillRect = "Fill a rectangle at pixel (x,y)"
|
||||
PythonFloat = "Convert x to a float"
|
||||
PythonFloor = "Floor"
|
||||
PythonFmod = "a modulo b"
|
||||
PythonFrExp = "Mantissa and exponent of x: (m,e)"
|
||||
PythonGamma = "Gamma function"
|
||||
PythonGetKeys = "Get keys pressed"
|
||||
PythonGetPalette = "Get theme palette"
|
||||
PythonGetPixel = "Return pixel (x,y) color"
|
||||
PythonGetrandbits = "Integer with k random bits"
|
||||
PythonGrid = "Toggle the visibility of the grid"
|
||||
@@ -69,6 +82,8 @@ PythonImportKandinsky = "Import kandinsky module"
|
||||
PythonImportRandom = "Import random module"
|
||||
PythonImportMath = "Import math module"
|
||||
PythonImportMatplotlibPyplot = "Import matplotlib.pyplot module"
|
||||
PythonImportNumpy = "Import ulab.numpy module"
|
||||
PythonImportScipy = "Import ulab.scipy module"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonImportTurtle = "Import turtle module"
|
||||
PythonIndex = "Index of the first x occurrence"
|
||||
@@ -79,6 +94,11 @@ PythonIonFunction = "ion module function prefix"
|
||||
PythonIsFinite = "Check if x is finite"
|
||||
PythonIsInfinite = "Check if x is infinity"
|
||||
PythonIsKeyDown = "Return True if the k key is down"
|
||||
PythonBattery = "Return battery voltage"
|
||||
PythonBatteryLevel = "Return battery level"
|
||||
PythonBatteryIscharging = "Return if battery is charging"
|
||||
PythonSetBrightness = "Set brightness level"
|
||||
PythonGetBrightness = "Get brightness level"
|
||||
PythonIsNaN = "Check if x is a NaN"
|
||||
PythonKandinskyFunction = "kandinsky module function prefix"
|
||||
PythonKeyLeft = "LEFT ARROW key"
|
||||
@@ -139,6 +159,14 @@ PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "Fractional and integer parts of x"
|
||||
PythonMonotonic = "Value of a monotonic clock"
|
||||
PythonNumpyFunction = "numpy module prefix"
|
||||
PythonNumpyFftFunction = "numpy.fft module prefix"
|
||||
PythonNumpyLinalgFunction = "numpy.linalg module prefix"
|
||||
PythonScipyFunction = "scipy module prefix"
|
||||
PythonScipyLinalgFunction = "scipy.linalg module prefix"
|
||||
PythonScipyOptimizeFunction = "scipy.optimize module prefix"
|
||||
PythonScipySignalFunction = "scipy.signal module prefix"
|
||||
PythonScipySpecialFunction = "scipy.special module prefix"
|
||||
PythonOct = "Convert integer to octal"
|
||||
PythonPhase = "Phase of z"
|
||||
PythonPlot = "Plot y versus x as lines"
|
||||
@@ -148,7 +176,7 @@ PythonPower = "x raised to the power y"
|
||||
PythonPrint = "Print object"
|
||||
PythonRadians = "Convert x from degrees to radians"
|
||||
PythonRandint = "Random integer in [a,b]"
|
||||
PythonRandom = "Floating point number in [0,1["
|
||||
PythonRandom = "Floating point number in [0,1]"
|
||||
PythonRandomFunction = "random module function prefix"
|
||||
PythonRandrange = "Random number in range(start,stop)"
|
||||
PythonRangeStartStop = "List from start to stop-1"
|
||||
@@ -164,6 +192,12 @@ PythonShow = "Display the figure"
|
||||
PythonSin = "Sine"
|
||||
PythonSinh = "Hyperbolic sine"
|
||||
PythonSleep = "Suspend the execution for t seconds"
|
||||
PythonLocalTime = "Convert time into tuple"
|
||||
PythonMktime = "Convert tuple into time"
|
||||
PythonTime = "Get the current timestamp"
|
||||
PythonSetLocaltime = "Set time from a tuple"
|
||||
PythonRTCmode = "Get current RTC mode"
|
||||
PythonSetRTCmode = "Set RTC mode"
|
||||
PythonSort = "Sort the list"
|
||||
PythonSqrt = "Square root"
|
||||
PythonSum = "Sum the items of a list"
|
||||
@@ -190,19 +224,25 @@ PythonTurtlePosition = "Return the current (x,y) location"
|
||||
PythonTurtleReset = "Reset the drawing"
|
||||
PythonTurtleRight = "Turn right by a degrees"
|
||||
PythonTurtleSetheading = "Set the orientation to a degrees"
|
||||
PythonTurtleSetposition = "Positionne la tortue"
|
||||
PythonTurtleShowturtle = "Show the turtle"
|
||||
PythonTurtleSpeed = "Drawing speed between 0 and 10"
|
||||
PythonTurtleWrite = "Display a text"
|
||||
PythonUniform = "Floating point number in [a,b]"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonImportOs = "Import os module"
|
||||
PythonImportSys = "Import sys module"
|
||||
PythonOsUname = "Get infos about the system"
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Remove file named filename"
|
||||
PythonOsRename = "Rename file oldname to newname"
|
||||
PythonOsListdir = "List files in memory"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Wait for n second"
|
||||
PythonSysExit = "Terminate current program"
|
||||
PythonSysPrintexception = "Print exception"
|
||||
PythonSysByteorder = "The byte order of the system"
|
||||
PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
PythonMonotonic = "Return monotonic time"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
@@ -220,3 +260,6 @@ PythonFileName = "Contains file's name"
|
||||
PythonFileMode = "Contains file's open mode"
|
||||
PythonFileReadable = "Tells if read can be used on a file"
|
||||
PythonFileWritable = "Tells if write can be used on a file"
|
||||
PythonImportUtils = "Importing ulab.utils"
|
||||
PythonUtilsFunction = "utils module function prefix"
|
||||
PythonTurtleBgcolor = "Change the background color"
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
PythonPound = "Comment"
|
||||
PythonPercent = "Modulo"
|
||||
PythonColon = "Colon"
|
||||
PythonSemicon = "Semicolon"
|
||||
PythonExclamationMark = "Exclamation mark"
|
||||
PythonLessThan = "Less than"
|
||||
PythonGreaterThan = "Greater than"
|
||||
PythonQuestionMark = "Question mark"
|
||||
Python1J = "Imaginary i"
|
||||
PythonLF = "Line feed"
|
||||
PythonTab = "Tabulation"
|
||||
@@ -30,8 +36,8 @@ PythonColor = "Define a rgb color"
|
||||
PythonColorBlack = "Black color"
|
||||
PythonColorBlue = "Blue color"
|
||||
PythonColorBrown = "Brown color"
|
||||
PythonColorGray = "Gray color"
|
||||
PythonColorGreen = "Green color"
|
||||
PythonColorGrey = "Grey color"
|
||||
PythonColorOrange = "Orange color"
|
||||
PythonColorPink = "Pink color"
|
||||
PythonColorPurple = "Purple color"
|
||||
@@ -45,19 +51,26 @@ PythonCosh = "Hyperbolic cosine"
|
||||
PythonCount = "Count the occurrences of x"
|
||||
PythonDegrees = "Convert x from radians to degrees"
|
||||
PythonDivMod = "Quotient and remainder"
|
||||
PythonDrawCircle = "Draw a circle"
|
||||
PythonDrawLine = "Draw a line"
|
||||
PythonDrawString = "Display a text from pixel (x,y)"
|
||||
PythonErf = "Error function"
|
||||
PythonErfc = "Complementary error function"
|
||||
PythonEval = "Return the evaluated expression"
|
||||
PythonExp = "Exponential function"
|
||||
PythonExpm1 = "Compute exp(x)-1"
|
||||
PythonFactorial = "factorial de x"
|
||||
PythonFabs = "Absolute value"
|
||||
PythonFillCircle = "Fill a circle"
|
||||
PythonFillPolygon = "Fill a polygon"
|
||||
PythonFillRect = "Fill a rectangle at pixel (x,y)"
|
||||
PythonFloat = "Convert x to a float"
|
||||
PythonFloor = "Floor"
|
||||
PythonFmod = "a modulo b"
|
||||
PythonFrExp = "Mantissa and exponent of x: (m,e)"
|
||||
PythonGamma = "Gamma function"
|
||||
PythonGetKeys = "Obtener teclas presionadas"
|
||||
PythonGetPalette = "Get theme palette"
|
||||
PythonGetPixel = "Return pixel (x,y) color"
|
||||
PythonGetrandbits = "Integer with k random bits"
|
||||
PythonGrid = "Toggle the visibility of the grid"
|
||||
@@ -69,6 +82,8 @@ PythonImportKandinsky = "Import kandinsky module"
|
||||
PythonImportRandom = "Import random module"
|
||||
PythonImportMath = "Import math module"
|
||||
PythonImportMatplotlibPyplot = "Import matplotlib.pyplot module"
|
||||
PythonImportNumpy = "Import ulab.numpy module"
|
||||
PythonImportScipy = "Import ulab.scipy module"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonImportTurtle = "Import turtle module"
|
||||
PythonIndex = "Index of the first x occurrence"
|
||||
@@ -79,6 +94,11 @@ PythonIonFunction = "ion module function prefix"
|
||||
PythonIsFinite = "Check if x is finite"
|
||||
PythonIsInfinite = "Check if x is infinity"
|
||||
PythonIsKeyDown = "Return True if the k key is down"
|
||||
PythonBattery = "Rückgabe der Batteriespannung"
|
||||
PythonBatteryLevel = "Gibt den Batteriestand zurück"
|
||||
PythonBatteryIscharging = "Gibt zurück, ob die Batterie geladen wird"
|
||||
PythonSetBrightness = "Establecer nivel de brillo"
|
||||
PythonGetBrightness = "Obtener nivel de brillo"
|
||||
PythonIsNaN = "Check if x is a NaN"
|
||||
PythonKandinskyFunction = "kandinsky module function prefix"
|
||||
PythonKeyLeft = "LEFT ARROW key"
|
||||
@@ -139,6 +159,14 @@ PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "Fractional and integer parts of x"
|
||||
PythonMonotonic = "Value of a monotonic clock"
|
||||
PythonNumpyFunction = "numpy module prefix"
|
||||
PythonNumpyFftFunction = "numpy.fft module prefix"
|
||||
PythonNumpyLinalgFunction = "numpy.linalg module prefix"
|
||||
PythonScipyFunction = "scipy module prefix"
|
||||
PythonScipyLinalgFunction = "scipy.linalg module prefix"
|
||||
PythonScipyOptimizeFunction = "scipy.optimize module prefix"
|
||||
PythonScipySignalFunction = "scipy.signal module prefix"
|
||||
PythonScipySpecialFunction = "scipy.special module prefix"
|
||||
PythonOct = "Convert integer to octal"
|
||||
PythonPhase = "Phase of z"
|
||||
PythonPlot = "Plot y versus x as lines"
|
||||
@@ -164,6 +192,12 @@ PythonShow = "Display the figure"
|
||||
PythonSin = "Sine"
|
||||
PythonSinh = "Hyperbolic sine"
|
||||
PythonSleep = "Suspend the execution for t seconds"
|
||||
PythonLocalTime = "Convertir el tiempo en tupla"
|
||||
PythonMktime = "Convertir tupla en tiempo"
|
||||
PythonTime = "Obtener la marca de tiempo actual"
|
||||
PythonSetLocaltime = "Establecer tiempo desde una tupla"
|
||||
PythonRTCmode = "Obtener el modo RTC actual"
|
||||
PythonSetRTCmode = "Establecer modo RTC"
|
||||
PythonSort = "Sort the list"
|
||||
PythonSqrt = "Square root"
|
||||
PythonSum = "Sum the items of a list"
|
||||
@@ -190,19 +224,25 @@ PythonTurtlePosition = "Return the current (x,y) location"
|
||||
PythonTurtleReset = "Reset the drawing"
|
||||
PythonTurtleRight = "Turn right by a degrees"
|
||||
PythonTurtleSetheading = "Set the orientation to a degrees"
|
||||
PythonTurtleSetposition = "Positionne la tortue"
|
||||
PythonTurtleShowturtle = "Show the turtle"
|
||||
PythonTurtleSpeed = "Drawing speed between 0 and 10"
|
||||
PythonTurtleWrite = "Display a text"
|
||||
PythonUniform = "Floating point number in [a,b]"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonImportOs = "Import os module"
|
||||
PythonImportSys = "Import sys module"
|
||||
PythonOsUname = " Información del sistema "
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Eliminar un archivo"
|
||||
PythonOsRename = "Renombrar archivo"
|
||||
PythonOsListdir = "Archivos de la lista"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Esperar n segundos"
|
||||
PythonSysExit = "Terminate current program"
|
||||
PythonSysPrintexception = "Print exception"
|
||||
PythonSysByteorder = "The byte order of the system"
|
||||
PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
PythonMonotonic = "Tiempo monótono de retorno"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
@@ -220,3 +260,6 @@ PythonFileName = "Contains file's name"
|
||||
PythonFileMode = "Contains file's open mode"
|
||||
PythonFileReadable = "Tells if read can be used on a file"
|
||||
PythonFileWritable = "Tells if write can be used on a file"
|
||||
PythonImportUtils = "Importando ulab.utils"
|
||||
PythonUtilsFunction = "prefijo de función del módulo utils"
|
||||
PythonTurtleBgcolor = "Cambiar el color de fondo"
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
PythonPound = "Commentaire"
|
||||
PythonPercent = "Modulo"
|
||||
PythonColon = "Deux-points"
|
||||
PythonSemicon = "Point-virgule"
|
||||
PythonExclamationMark = "Point d'exclamation"
|
||||
PythonLessThan = "Inférieur à"
|
||||
PythonGreaterThan = "Supérieur à"
|
||||
PythonQuestionMark = "Point d'interrogation"
|
||||
Python1J = "i complexe"
|
||||
PythonLF = "Saut à la ligne"
|
||||
PythonTab = "Tabulation"
|
||||
@@ -30,8 +36,8 @@ PythonColor = "Définit une couleur rvb"
|
||||
PythonColorBlack = "Couleur noire"
|
||||
PythonColorBlue = "Couleur bleue"
|
||||
PythonColorBrown = "Couleur marron"
|
||||
PythonColorGray = "Couleur grise"
|
||||
PythonColorGreen = "Couleur verte"
|
||||
PythonColorGrey = "Couleur grise"
|
||||
PythonColorOrange = "Couleur orange"
|
||||
PythonColorPink = "Couleur rose"
|
||||
PythonColorPurple = "Couleur violette"
|
||||
@@ -45,19 +51,26 @@ PythonCosh = "Cosinus hyperbolique"
|
||||
PythonCount = "Compte les occurrences de x"
|
||||
PythonDegrees = "Conversion de radians en degrés"
|
||||
PythonDivMod = "Quotient et reste"
|
||||
PythonDrawCircle = "Trace un cercle"
|
||||
PythonDrawLine = "Trace une ligne"
|
||||
PythonDrawString = "Affiche un texte au pixel (x,y)"
|
||||
PythonErf = "Fonction d'erreur"
|
||||
PythonErfc = "Fonction d'erreur complémentaire"
|
||||
PythonEval = "Evalue l'expression en argument "
|
||||
PythonExp = "Fonction exponentielle"
|
||||
PythonExpm1 = "Calcul de exp(x)-1"
|
||||
PythonFactorial = "Factorielle de x"
|
||||
PythonFabs = "Valeur absolue"
|
||||
PythonFillCircle = "Remplit un cercle"
|
||||
PythonFillPolygon = "Remplit un polygone"
|
||||
PythonFillRect = "Remplit un rectangle"
|
||||
PythonFloat = "Conversion en flottant"
|
||||
PythonFloor = "Partie entière"
|
||||
PythonFmod = "a modulo b"
|
||||
PythonFrExp = "Mantisse et exposant de x : (m,e)"
|
||||
PythonGamma = "Fonction gamma"
|
||||
PythonGetKeys = "Obtenir les touches pressées"
|
||||
PythonGetPalette = "Obtient la palette du thème"
|
||||
PythonGetPixel = "Renvoie la couleur du pixel (x,y)"
|
||||
PythonGetrandbits = "Nombre aléatoire sur k bits"
|
||||
PythonGrid = "Affiche ou masque la grille"
|
||||
@@ -69,6 +82,9 @@ PythonImportKandinsky = "Importation du module kandinsky"
|
||||
PythonImportRandom = "Importation du module random"
|
||||
PythonImportMath = "Importation du module math"
|
||||
PythonImportMatplotlibPyplot = "Importation de matplotlib.pyplot"
|
||||
PythonImportNumpy = "Importation de ulab.numpy"
|
||||
PythonImportScipy = "Importation de ulab.scipy"
|
||||
PythonImportUtils = "Importation de ulab.utils"
|
||||
PythonImportTurtle = "Importation du module turtle"
|
||||
PythonImportTime = "Importation du module time"
|
||||
PythonIndex = "Indice première occurrence de x"
|
||||
@@ -79,6 +95,11 @@ PythonIonFunction = "Préfixe fonction module ion"
|
||||
PythonIsFinite = "Teste si x est fini"
|
||||
PythonIsInfinite = "Teste si x est infini"
|
||||
PythonIsKeyDown = "Renvoie True si touche k enfoncée"
|
||||
PythonBattery = "Renvoie le voltage de la batterie"
|
||||
PythonBatteryLevel = "Renvoie le niveau de la batterie"
|
||||
PythonBatteryIscharging = "Chargement en cours"
|
||||
PythonSetBrightness = "Définir le niveau de luminosité"
|
||||
PythonGetBrightness = "Obtenir le niveau de luminosité"
|
||||
PythonIsNaN = "Teste si x est NaN"
|
||||
PythonKandinskyFunction = "Préfixe fonction module kandinsky"
|
||||
PythonKeyLeft = "Touche FLECHE GAUCHE"
|
||||
@@ -139,6 +160,15 @@ PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "Parties fractionnaire et entière"
|
||||
PythonMonotonic = "Renvoie la valeur de l'horloge"
|
||||
PythonNumpyFunction = "Préfixe fonction du module numpy"
|
||||
PythonNumpyFftFunction = "Préfixe fonction du module numpy.fft"
|
||||
PythonNumpyLinalgFunction = "Préfixe fonction du module numpy.linalg"
|
||||
PythonScipyFunction = "Préfixe fonction du module scipy"
|
||||
PythonScipyLinalgFunction = "Préfixe fonction du module scipy.linalg"
|
||||
PythonScipyOptimizeFunction = "Préfixe fonction du module scipy.optimize"
|
||||
PythonScipySignalFunction = "Préfixe fonction du module scipy.signal"
|
||||
PythonScipySpecialFunction = "Préfixe fonction du module scipy.special"
|
||||
PythonUtilsFunction = "Préfixe fonction du module utils"
|
||||
PythonOct = "Conversion en octal"
|
||||
PythonPhase = "Argument de z"
|
||||
PythonPlot = "Trace y en fonction de x"
|
||||
@@ -154,7 +184,7 @@ PythonRandrange = "Nombre dans range(start,stop)"
|
||||
PythonRangeStartStop = "Liste de start à stop-1"
|
||||
PythonRangeStop = "Liste de 0 à stop-1"
|
||||
PythonRect = "Conversion en algébrique"
|
||||
PythonRemove = "Supprime le premier x de la liste"
|
||||
PythonRemove = "Supprime le premier x de la liste"
|
||||
PythonReverse = "Inverse les éléments de la liste"
|
||||
PythonRound = "Arrondi à n décimales"
|
||||
PythonScatter = "Nuage des points (x,y)"
|
||||
@@ -164,6 +194,12 @@ PythonShow = "Affiche la figure"
|
||||
PythonSin = "Sinus"
|
||||
PythonSinh = "Sinus hyperbolique"
|
||||
PythonSleep = "Suspend l'exécution t secondes"
|
||||
PythonLocalTime = "Convertir le temps en tuple"
|
||||
PythonMktime = "Convertir le tuple en temps"
|
||||
PythonTime = "Obtenir l'horodatage actuel"
|
||||
PythonSetLocaltime = "Définir l'heure à partir d'un tuple"
|
||||
PythonRTCmode = "Obtenir le mode RTC actuel"
|
||||
PythonSetRTCmode = "Définir le mode RTC"
|
||||
PythonSort = "Trie la liste"
|
||||
PythonSqrt = "Racine carrée"
|
||||
PythonSum = "Somme des éléments de la liste"
|
||||
@@ -176,6 +212,7 @@ PythonTurtleBackward = "Recule de x pixels"
|
||||
PythonTurtleCircle = "Cercle de rayon r pixels"
|
||||
PythonTurtleColor = "Modifie la couleur du tracé"
|
||||
PythonTurtleColorMode = "Met le mode de couleur à 1.0 ou 255"
|
||||
PythonTurtleBgcolor = "Modifie la couleur du fond"
|
||||
PythonTurtleForward = "Avance de x pixels"
|
||||
PythonTurtleFunction = "Préfixe fonction du module turtle"
|
||||
PythonTurtleGoto = "Va au point de coordonnées (x,y)"
|
||||
@@ -190,32 +227,38 @@ PythonTurtlePosition = "Renvoie la position (x,y)"
|
||||
PythonTurtleReset = "Réinitialise le dessin"
|
||||
PythonTurtleRight = "Pivote de a degrés vers la droite"
|
||||
PythonTurtleSetheading = "Met un cap de a degrés"
|
||||
PythonTurtleSetposition = "Positionne la tortue"
|
||||
PythonTurtleShowturtle = "Affiche la tortue"
|
||||
PythonTurtleSpeed = "Vitesse du tracé entre 0 et 10"
|
||||
PythonTurtleWrite = "Affiche un texte"
|
||||
PythonUniform = "Nombre décimal dans [a,b]"
|
||||
PythonImportTime = "Importation du module temps"
|
||||
PythonImportOs = "Importation du module os"
|
||||
PythonImportSys = "Importation du module sys"
|
||||
PythonOsUname = "Donne des infos sur le système"
|
||||
PythonOsGetlogin = "Donne le nom d'utilisateur"
|
||||
PythonOsRemove = "Supprime le fichier nommé filename"
|
||||
PythonOsRename = "Renomme oldname en newname"
|
||||
PythonOsListdir = "Liste les fichiers"
|
||||
PythonTimePrefix = "Préfixe fonction du module temps"
|
||||
PythonTimeSleep = "Attendre n secondes"
|
||||
PythonMonotonic = "Retourne le temps monotonic"
|
||||
PythonSysExit = "Termine le programme"
|
||||
PythonSysPrintexception = "Imprime une exception"
|
||||
PythonSysByteorder = "L'ordre des octets du système"
|
||||
PythonSysImplementation = "Information sur Python"
|
||||
PythonSysModules = "Dictionnaire des modules chargés"
|
||||
PythonSysVersion = "Version du langage Python (string)"
|
||||
PythonSysVersioninfo = "Version du langage Python (tuple)"
|
||||
PythonMonotonic = "Retourne le temps monotone"
|
||||
PythonFileOpen = "Ouvre un fichier"
|
||||
PythonFileSeekable = "Indique si seek peut être utilisé"
|
||||
PythonFileSeek = "Déplace le curseur interne"
|
||||
PythonFileTell = "Donne la posititon du curseur"
|
||||
PythonFileClose = "Ferme un fichier"
|
||||
PythonFileClosed = "True si le fichier a été fermé"
|
||||
PythonFileRead = "Lis jusqu'à size bytes"
|
||||
PythonFileWrite = "Écris b dans le fichier"
|
||||
PythonFileReadline = "Lis une ligne ou jusqu'à size bytes"
|
||||
PythonFileReadlines = "Lis une liste de lignes"
|
||||
PythonFileRead = "Lit jusqu'à size bytes"
|
||||
PythonFileWrite = "Écrit b dans le fichier"
|
||||
PythonFileReadline = "Lit une ligne ou jusqu'à size bytes"
|
||||
PythonFileReadlines = "Lit une liste de lignes"
|
||||
PythonFileTruncate = "Redimensionne le fichier"
|
||||
PythonFileWritelines = "Écris une liste de lignes"
|
||||
PythonFileWritelines = "Écrit une liste de lignes"
|
||||
PythonFileName = "Nom du fichier"
|
||||
PythonFileMode = "Mode d'ouverture du fichier"
|
||||
PythonFileReadable = "Indique si read peut être utilisé"
|
||||
|
||||
@@ -1,222 +1,265 @@
|
||||
PythonPound = "Megjegyzés"
|
||||
PythonPercent = "Modulo"
|
||||
Python1J = "Képzeletbeli i"
|
||||
PythonLF = "Line feed"
|
||||
PythonTab = "Táblázat"
|
||||
PythonAmpersand = "Bitwise és"
|
||||
PythonSymbolExp = "Bitwise exkluzív vagy"
|
||||
PythonVerticalBar = "Bitwise vagy"
|
||||
PythonImag = "z képzeletbeli része"
|
||||
PythonReal = "z valódi része"
|
||||
PythonSingleQuote = "Egyetlen idézet"
|
||||
PythonAbs = "Abszolút érték / nagyság"
|
||||
PythonAcos = "Arc koszinusz"
|
||||
PythonAcosh = "Íves hiperbolikus koszinusz"
|
||||
PythonAppend = "x hozzáadása a lista végéhez"
|
||||
PythonArrow = "Arrow from (x,y) to (x+dx,y+dy)"
|
||||
PythonAsin = "Arc szinusz"
|
||||
PythonAsinh = "Íves hiperbolikus szinusz"
|
||||
PythonAtan = "Arc érintö"
|
||||
PythonAtan2 = "Visszatérés atan (y / x)"
|
||||
PythonAtanh = "Arc hiperbolikus érintö"
|
||||
PythonAxis = "Set axes to (xmin,xmax,ymin,ymax)"
|
||||
PythonBar = "Draw a bar plot with x values"
|
||||
PythonBin = "Egész szám konvertálása binárisra"
|
||||
PythonCeil = "Mennyezet"
|
||||
PythonChoice = "Véletlenszerü szám a listában"
|
||||
PythonClear = "A lista ürítése"
|
||||
PythonCmathFunction = "cmath modul funkció elötag"
|
||||
PythonColor = "Rgb szín meghatározása"
|
||||
PythonColorBlack = "Fekete szín"
|
||||
PythonColorBlue = "Kék szín"
|
||||
PythonColorBrown = "Barna szín"
|
||||
PythonColorGreen = "Zöld szín"
|
||||
PythonColorGrey = "Szürke szín"
|
||||
PythonColorOrange = "Narancssárga szín"
|
||||
PythonColorPink = "Rózsaszín szín"
|
||||
PythonColorPurple = "Lila szín"
|
||||
PythonColorRed = "Piros szín"
|
||||
PythonColorWhite = "White color"
|
||||
PythonColorYellow = "Sárga szín"
|
||||
PythonComplex = "A + ib visszaadása"
|
||||
PythonCopySign = "Visszatérés x-val y jelével"
|
||||
PythonCos = "Koszinusz"
|
||||
PythonCosh = "Hiperbolikus koszinusz"
|
||||
PythonCount = "Számolja az x elöfordulását"
|
||||
PythonDegrees = "x konvertálása x-röl radiánokra fokokra"
|
||||
PythonDivMod = "Hányados és maradék"
|
||||
PythonDrawString = "Szöveg megjelenítése pixelböl (x, y)"
|
||||
PythonErf = "Hiba funkció"
|
||||
PythonErfc = "Kiegészítö hibafunkció"
|
||||
PythonEval = "Visszaadja az értékelt kifejezést"
|
||||
PythonExp = "Exponenciális függvény"
|
||||
PythonExpm1 = "Számítsuk ki az exp (x) -1-et"
|
||||
PythonFabs = "Abszolút érték"
|
||||
PythonFillRect = "Töltsön meg egy téglalapot pixelnél (x, y)"
|
||||
PythonFloat = "x konvertálása float-ra"
|
||||
PythonFloor = "Emelet"
|
||||
PythonFmod = "a modulo b"
|
||||
PythonFrExp = "Mantissa és az x exponense"
|
||||
PythonGamma = "Gamma funkció"
|
||||
PythonGetPixel = "Visszatérési pixel (x, y) szín"
|
||||
PythonGetrandbits = "Egész szám k véletlen bittel"
|
||||
PythonGrid = "Toggle the visibility of the grid"
|
||||
PythonHex = "Egész szám konvertálása hexadecimálisra"
|
||||
PythonHist = "Draw the histogram of x"
|
||||
PythonImportCmath = "cmath modul importálása"
|
||||
PythonImportIon = "Ion modul importálása"
|
||||
PythonImportKandinsky = "Kandinsky modul importálása"
|
||||
PythonImportRandom = "Véletlenszerü modul importálása"
|
||||
PythonImportMath = "Import matematikai modul"
|
||||
PythonImportMatplotlibPyplot = "Import matplotlib.pyplot module"
|
||||
PythonImportTime = "Idömodul importálása"
|
||||
PythonImportOs = "Os modul importálása"
|
||||
PythonOsUname = "Információ a rendszerről"
|
||||
PythonOsRemove = "Fájl eltávolítása"
|
||||
PythonOsRename = "Fájl átnevezése"
|
||||
PythonOsListdir = "Fájlok listázása"
|
||||
PythonImportTurtle = "Import teknös modul"
|
||||
PythonIndex = "Az elsö x esemény indexe"
|
||||
PythonInput = "Érték kérése"
|
||||
PythonInsert = "Helyezzen x-t az i indexbe a listában"
|
||||
PythonInt = "x konvertálása egész számra"
|
||||
PythonIonFunction = "ion modul funkció elötag"
|
||||
PythonIsFinite = "Ellenörizze, hogy x véges-e"
|
||||
PythonIsInfinite = "Ellenörizze, hogy x végtelen-e"
|
||||
PythonIsKeyDown = "True true, ha a k gomb le van nyomva"
|
||||
PythonIsNaN = "Ellenörizze, hogy x nem NaN"
|
||||
PythonKandinskyFunction = "kandinsky modul function prefix"
|
||||
PythonKeyLeft = "Balra nyíl gomb"
|
||||
PythonKeyUp = "FEL NYÍL gomb"
|
||||
PythonKeyDown = "LE nyíl gomb"
|
||||
PythonKeyRight = "JOBB NYÍL gomb"
|
||||
PythonKeyOk = "OK gomb"
|
||||
PythonKeyBack = "VISSZA kulcs"
|
||||
PythonKeyHome = "HOME kulcs"
|
||||
PythonKeyOnOff = "BE / KI gomb"
|
||||
PythonKeyShift = "SHIFT kulcs"
|
||||
PythonKeyAlpha = "ALPHA kulcs"
|
||||
PythonKeyXnt = "X, N, T kulcs"
|
||||
PythonKeyVar = "VAR kulcs"
|
||||
PythonKeyToolbox = "TOOLBOX kulcs"
|
||||
PythonKeyBackspace = "BACKSPACE kulcs"
|
||||
PythonKeyExp = "EXPONENTIAL kulcs"
|
||||
PythonKeyLn = "NATURAL LOGARITHM kulcs"
|
||||
PythonKeyLog = "DECIMAL LOGARITHM kulcs"
|
||||
PythonKeyImaginary = "IMAGINÁRIS I kulcs"
|
||||
PythonKeyComma = "COMMA kulcs"
|
||||
PythonKeyPower = "POWER kulcs"
|
||||
PythonKeySine = "SINE kulcs"
|
||||
PythonKeyCosine = "KOSZIN kulcs"
|
||||
PythonKeyTangent = "TANGENT kulcs"
|
||||
PythonKeyPi = "PI kulcs"
|
||||
PythonKeySqrt = "SQUARE ROOT kulcs"
|
||||
PythonKeySquare = "SQUARE kulcs"
|
||||
PythonKeySeven = "7 kulcs"
|
||||
PythonKeyEight = "8 kulcs"
|
||||
PythonKeyNine = "9 kulcs"
|
||||
PythonKeyLeftParenthesis = "Bal oldali PARENTHESIS kulcs"
|
||||
PythonKeyRightParenthesis = "JOGOS SZÜLETÉS kulcs"
|
||||
PythonKeyFour = "4 kulcs"
|
||||
PythonKeyFive = "5 kulcs"
|
||||
PythonKeySix = "6 kulcs"
|
||||
PythonKeyMultiplication = "TÖBB MüKÖDÉS kulcs"
|
||||
PythonKeyDivision = "DIVISION kulcs"
|
||||
PythonKeyOne = "1 kulcs"
|
||||
PythonKeyTwo = "2 kulcs"
|
||||
PythonKeyThree = "3 kulcs"
|
||||
PythonKeyPlus = "PLUS kulcs"
|
||||
PythonKeyMinus = "MINUS kulcs"
|
||||
PythonKeyZero = "0 kulcs"
|
||||
PythonKeyDot = "DOT kulcs"
|
||||
PythonKeyEe = "10 POWER X kulcs"
|
||||
PythonKeyAns = "ANS kulcs"
|
||||
PythonKeyExe = "EXE kulcs"
|
||||
PythonLdexp = "Visszatérés x * (2 ** i), inverz a frexp értékhez"
|
||||
PythonLength = "Objektum hossza"
|
||||
PythonLgamma = "Log-gamma funkció"
|
||||
PythonLog = "Logaritmus az alap"
|
||||
PythonLog10 = "Logaritmus az alaphoz 10"
|
||||
PythonLog2 = "Logaritmus az alaphoz 2"
|
||||
PythonMathFunction = "matematikai modul funkció elötag"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot module prefix"
|
||||
PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "Az x tört és egész részei"
|
||||
PythonMonotonic = "A monoton óra értéke"
|
||||
PythonOct = "Egész szám konvertálása oktális értékre"
|
||||
PythonPhase = "z fázis"
|
||||
PythonPlot = "Plot y versus x as lines"
|
||||
PythonPolar = "z poláris koordinátákban"
|
||||
PythonPop = "Az utolsó elem eltávolítása és visszaküldése"
|
||||
PythonPower = "x emelve az y teljesítményre"
|
||||
PythonPrint = "Objektum nyomtatása"
|
||||
PythonRadians = "x konvertálása x fokról radiánra"
|
||||
PythonRandint = "Véletlen egész szám [a, b] -ben"
|
||||
PythonRandom = "Lebegöpontos szám [0,1-ben ["
|
||||
PythonRandomFunction = "véletlenszerü modul funkció elötag"
|
||||
PythonRandrange = "Véletlen szám a tartományban (start, stop)"
|
||||
PythonRangeStartStop = "Lista az elejétöl a stop-1-ig"
|
||||
PythonRangeStop = "Lista 0-tól stop-1-ig"
|
||||
PythonRect = "z derékszögü koordinátákban"
|
||||
PythonRemove = "Távolítsa el az x elsö elöfordulását"
|
||||
PythonReverse = "A lista elemeinek megfordítása"
|
||||
PythonRound = "N számjegyre kerekítve"
|
||||
PythonScatter = "Draw a scatter plot of y versus x"
|
||||
PythonSeed = "Inicializálja a véletlenszám-generátort"
|
||||
PythonSetPixel = "Színes pixel (x, y)"
|
||||
PythonShow = "Display the figure"
|
||||
PythonSin = "Sine"
|
||||
PythonSinh = "Hiperbolikus szinusz"
|
||||
PythonSleep = "A végrehajtás felfüggesztése t másodpercre"
|
||||
PythonSort = "A lista rendezése"
|
||||
PythonSqrt = "Négyzetgyök"
|
||||
PythonSum = "Összegzi a lista elemeit"
|
||||
PythonTan = "Érintö"
|
||||
PythonTanh = "Hiperbolikus érintö"
|
||||
PythonText = "Display a text at (x,y) coordinates"
|
||||
PythonTimeFunction = "idömodul funkció elötag"
|
||||
PythonTrunc = "x egészre csonkítva"
|
||||
PythonTurtleBackward = "Visszalépés x pixelrel"
|
||||
PythonTurtleCircle = "r pixel sugarú kör"
|
||||
PythonTurtleColor = "Állítsa be az toll színét"
|
||||
PythonTurtleColorMode = "Set the color mode to 1.0 or 255"
|
||||
PythonTurtleForward = "Ugrás x pixelrel"
|
||||
PythonTurtleFunction = "teknös modul funkció elötag"
|
||||
PythonTurtleGoto = "Mozgatás (x, y) koordinátákra"
|
||||
PythonTurtleHeading = "Visszaadja az aktuális címsort"
|
||||
PythonTurtleHideturtle = "A teknös elrejtése"
|
||||
PythonTurtleIsdown = "Visszatérés igazhoz, ha az toll lefelé"
|
||||
PythonTurtleLeft = "Forduljon fokkal balra"
|
||||
PythonTurtlePendown = "Húzza le a tollat"
|
||||
PythonTurtlePensize = "Állítsa a vonalvastagságot x pixelre"
|
||||
PythonTurtlePenup = "Húzza fel a tollat"
|
||||
PythonTurtlePosition = "Az aktuális (x, y) hely visszaadása"
|
||||
PythonTurtleReset = "A rajz visszaállítása"
|
||||
PythonTurtleRight = "Forduljon fokkal jobbra"
|
||||
PythonTurtleSetheading = "Állítsa be a tájolást fokokra"
|
||||
PythonTurtleSetposition = "A helymeghatározás"
|
||||
PythonTurtleShowturtle = "Mutasd a teknösöt"
|
||||
PythonTurtleSpeed = "Rajzolási sebesség 0 és 10 között"
|
||||
PythonTurtleWrite = "Display a text"
|
||||
PythonUniform = "Lebegöpontos szám [a, b] -ben"
|
||||
PythonImportTime = "Idömodul importálása"
|
||||
PythonTimePrefix = "idömodul funkció elötag"
|
||||
PythonTimeSleep = "Várj n másodpercet"
|
||||
PythonMonotonic = "Vissza a monoton idö"
|
||||
PythonFileOpen = "Fájl megnyitása"
|
||||
PythonFileSeekable = "A fájl kereshető?"
|
||||
PythonFileSeek = "A fájl kurzorának áthelyezése"
|
||||
PythonFileTell = "A fájl kurzorának helye"
|
||||
PythonFileClose = "Bezár egy fájlt"
|
||||
PythonFileClosed = "Igaz, ha a fájl bezárt"
|
||||
PythonFileRead = "Olvasson méretbájtig"
|
||||
PythonFileWrite = "B beírása fájlba"
|
||||
PythonFileReadline = "Olvas egy sort"
|
||||
PythonFileReadlines = "Olvassa a sorok listáját"
|
||||
PythonFileTruncate = "A fájl átméretezése méretre"
|
||||
PythonFileWritelines = "Sorok listáját írja"
|
||||
PythonFileName = "a fájl neve"
|
||||
PythonFileMode = "a fájl nyitott módja"
|
||||
PythonFileReadable = "A fájl olvasható?"
|
||||
PythonFileWritable = "A fájl írható?"
|
||||
PythonPound = "Megjegyzés"
|
||||
PythonPercent = "Modulo"
|
||||
PythonColon = "Kettőspont"
|
||||
PythonSemicon = "Pontosvessző"
|
||||
PythonExclamationMark = "Felkiáltójel"
|
||||
PythonLessThan = "Kisebb mint"
|
||||
PythonGreaterThan = "Nagyobb mint"
|
||||
PythonQuestionMark = "Kérdőjel"
|
||||
Python1J = "Képzeletbeli i"
|
||||
PythonLF = "Enter"
|
||||
PythonTab = "Táblázat"
|
||||
PythonAmpersand = "Logikus és"
|
||||
PythonSymbolExp = "logikus exkluzív vagy pedig"
|
||||
PythonVerticalBar = "logikus vagy pedig"
|
||||
PythonImag = "z képzeletbeli része"
|
||||
PythonReal = "z valódi része"
|
||||
PythonSingleQuote = "apostróf"
|
||||
PythonAbs = "Abszolút érték/nagyság"
|
||||
PythonAcos = "Ív (arc) koszinusz"
|
||||
PythonAcosh = "Hiperbolikus arc koszinusz"
|
||||
PythonAppend = "Lista végére hozzáadni x-et"
|
||||
PythonArrow = "(x,y) nyíla (x+dx,y+dy) nyílához"
|
||||
PythonAsin = "Ív (arc) szinusz"
|
||||
PythonAsinh = "Hiperbolikus ív (arc) szinusz"
|
||||
PythonAtan = "Ív (arc) érintö (tan)"
|
||||
PythonAtan2 = "atan(y/x) sámolása"
|
||||
PythonAtanh = "Hiperbolikus ív (arc) érintö (atan)"
|
||||
PythonAxis = "Tengelyeket (xmin,xmax,ymin,ymax)-ra állitani"
|
||||
PythonBar = "Az x lista oszlopdiagramja"
|
||||
PythonBin = "Egész szám konvertálása binárisra"
|
||||
PythonCeil = "Mennyezet"
|
||||
PythonChoice = "Véletlenszerü szám a listában"
|
||||
PythonClear = "A lista ürítése"
|
||||
PythonCmathFunction = "cmath modul funkció elötag"
|
||||
PythonColor = "Rgb (pzk) szín allítása"
|
||||
PythonColorBlack = "Fekete szín"
|
||||
PythonColorBlue = "Kék szín"
|
||||
PythonColorBrown = "Barna szín"
|
||||
PythonColorGreen = "Zöld szín"
|
||||
PythonColorGray = "Szürke szín"
|
||||
PythonColorOrange = "Narancssárga szín"
|
||||
PythonColorPink = "Rózsaszín szín"
|
||||
PythonColorPurple = "Lila szín"
|
||||
PythonColorRed = "Piros szín"
|
||||
PythonColorWhite = "Fehér szín"
|
||||
PythonColorYellow = "Sárga szín"
|
||||
PythonComplex = "A + ib visszaadása"
|
||||
PythonCopySign = "X visszaadása y jelével"
|
||||
PythonCos = "Koszinusz"
|
||||
PythonCosh = "Hiperbolikus koszinusz"
|
||||
PythonCount = "Számolja az x elöfordulását"
|
||||
PythonDegrees = "x konvertálása radiánokrol fokokra"
|
||||
PythonDivMod = "Hányados és maradék"
|
||||
PythonDrawCircle = "Rajzolj egy kört"
|
||||
PythonDrawLine = "Húzzon egy vonalat "
|
||||
PythonDrawString = "Szöveg megjelenítése (x, y)-en"
|
||||
PythonErf = "Hiba funkció"
|
||||
PythonErfc = "Kiegészítö hiba funkció"
|
||||
PythonEval = "Visszaadja az értékelt kifejezést"
|
||||
PythonExp = "Exponenciális függvény"
|
||||
PythonExpm1 = "exp(x)-1 sámitása"
|
||||
PythonFactorial = "x faktorál"
|
||||
PythonFabs = "Abszolút érték"
|
||||
PythonFillRect = "Téglalap töltése"
|
||||
PythonFillCircle = "Kitölti a kört"
|
||||
PythonFillPolygon = "Kitölti a poligont"
|
||||
PythonFloat = "Konvertálása tizedes számra"
|
||||
PythonFloor = "Egész része"
|
||||
PythonFmod = "a modulo b"
|
||||
PythonFrExp = "X mantissája és kiállítója"
|
||||
PythonGamma = "Gamma funkció"
|
||||
PythonGetKeys = "Billentyűk lenyomva"
|
||||
PythonGetPalette = "Téma paletta beszerzése"
|
||||
PythonGetPixel = "Visszatéríti (x,y) színét"
|
||||
PythonGetrandbits = "Váletlenszám visszatérítése k biten"
|
||||
PythonGrid = "Rács megjelenítése/elrejtése"
|
||||
PythonHex = "Decimális szám konvertálása hexadecimális számra"
|
||||
PythonHist = "x hisztográmiája"
|
||||
PythonImportCmath = "cmath modul importálása"
|
||||
PythonImportIon = "Ion modul importálása"
|
||||
PythonImportKandinsky = "Kandinsky modul importálása"
|
||||
PythonImportRandom = "Véletlenszerü modul importálása"
|
||||
PythonImportMath = "math modul importálása"
|
||||
PythonImportMatplotlibPyplot = "matplotlib.pyplot modul importálása"
|
||||
PythonImportNumpy = "ulab.numpy modul importálása"
|
||||
PythonImportScipy = "ulab.scipy modul importálása"
|
||||
PythonImportTurtle = "turtle modul importálása"
|
||||
PythonImportTime = "time modul importálása"
|
||||
PythonIndex = "Az elsö x esemény indexe"
|
||||
PythonInput = "Irjon egy értéket (számot)"
|
||||
PythonInsert = "x-et i. pozícióra helyezze a listában"
|
||||
PythonInt = "egész számra konvertálás"
|
||||
PythonIonFunction = "ion modul funkció elötag"
|
||||
PythonIsFinite = "x véges-e"
|
||||
PythonIsInfinite = "x végtelen-e"
|
||||
PythonIsKeyDown = "True-t válaszol ha a k gomb le van nyomva"
|
||||
PythonBattery = "Az akkumulátor feszültségének visszaadása"
|
||||
PythonBatteryLevel = "Az akkumulátor töltöttségi szintjének visszaadása"
|
||||
PythonBatteryIscharging = "Visszaadja, ha az akkumulátor töltődik"
|
||||
PythonSetBrightness = "Fényerőszint beállítása"
|
||||
PythonGetBrightness = "Get brightness level"
|
||||
PythonIsNaN = "Ellenörizze hogy x nem NaN"
|
||||
PythonKandinskyFunction = "kandinsky modul funkció elötag"
|
||||
PythonLdexp = "frexp ellentéte : x*(2**i)"
|
||||
PythonLength = "Egy targy hossza"
|
||||
PythonLgamma = "Gamma funkció logaritmusa"
|
||||
PythonLog = "a alapú logaritmus"
|
||||
PythonLog10 = "Decimális logaritmus"
|
||||
PythonLog2 = "Bináris logaritmus"
|
||||
PythonMathFunction = "math modul funkció elötag"
|
||||
PythonMatplotlibPyplotFunction = "matplotlib.pyplot elötag"
|
||||
PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "x-nek tört és egész részei"
|
||||
PythonMonotonic = "Az óra értékét adja vissza"
|
||||
PythonNumpyFunction = "numpy elötag"
|
||||
PythonNumpyFftFunction = "numpy.fft elötag"
|
||||
PythonNumpyLinalgFunction = "numpy.linalg elötag"
|
||||
PythonScipyFunction = "scipy elötag"
|
||||
PythonScipyLinalgFunction = "scipy.linalg elötag"
|
||||
PythonScipyOptimizeFunction = "scipy.optimize elötag"
|
||||
PythonScipySignalFunction = "scipy.signal elötag"
|
||||
PythonScipySpecialFunction = "scipy.special elötag"
|
||||
PythonOct = "Decimális szám konvertálása octális számra"
|
||||
PythonPhase = "z fázisa"
|
||||
PythonPlot = "y-t jelöli x függvényében"
|
||||
PythonPolar = "Verctorizálni"
|
||||
PythonPop = "Az utolsó elemet el törölni"
|
||||
PythonPower = "x y. kitevö"
|
||||
PythonPrint = "Ki irni a elemeket"
|
||||
PythonRadians = "Fokról radiánra konvertálni"
|
||||
PythonRandint = "Véletlen egész szám [a;b] -ban"
|
||||
PythonRandom = "Decimális szám [0;1] -ban"
|
||||
PythonRandomFunction = "random modul funkció elötag"
|
||||
PythonRandrange = "Véletlen szám range(start,stop)-ban"
|
||||
PythonRangeStartStop = "start-tol stop-ig listája"
|
||||
PythonRangeStop = "0 tol stop-ig lista"
|
||||
PythonRect = "Algebrai számra konvertálni"
|
||||
PythonRemove = "Elsö x elöfordulását törolni"
|
||||
PythonReverse = "A lista elemeit megfordítani (másik irány)"
|
||||
PythonRound = "N számjegyre kerekítni"
|
||||
PythonScatter = "(x,y) halmaza"
|
||||
PythonSeed = "Inicializálni a véletlenszám-választót"
|
||||
PythonSetPixel = "Az (x,y) pixel-t ki szinezni"
|
||||
PythonShow = "Mutassa az ábrát"
|
||||
PythonSin = "Szinusz"
|
||||
PythonSinh = "Hiperbolikus szinusz"
|
||||
PythonSleep = "t másodpercre meg állitani a programmot"
|
||||
PythonLocalTime = "Idő konvertálása csomóvá"
|
||||
PythonMktime = "A tuple konvertálása az időben"
|
||||
PythonTime = "Az aktuális időbélyeg letöltése"
|
||||
PythonSetLocaltime = "Idő beállítása egy csomóból"
|
||||
PythonRTCmode = "Aktuális RTC mód"
|
||||
PythonSetRTCmode = "RTC mód beállítása"
|
||||
PythonSort = "A listát rendezni"
|
||||
PythonSqrt = "Négyzetgyök"
|
||||
PythonSum = "Összeadni a lista elemeit"
|
||||
PythonTan = "Érintö (tan)"
|
||||
PythonTanh = "Hiperbolikus érintö (tan)"
|
||||
PythonText = "(x,y) nél egy szöveget irni"
|
||||
PythonTimeFunction = "time funkció elötag"
|
||||
PythonTrunc = "Egész csonka (?)"
|
||||
PythonTurtleBackward = "x pixelt hátra"
|
||||
PythonTurtleCircle = "r pixel sugarú kört rajzolni"
|
||||
PythonTurtleColor = "Toll szinét beállitani"
|
||||
PythonTurtleColorMode = "Szin módot 1.0-ra vagy 255-ra állitani"
|
||||
PythonTurtleForward = "x pixelt elölre"
|
||||
PythonTurtleFunction = "turtle modul funkció elötag"
|
||||
PythonTurtleGoto = "Menjen a (x,y) koordinátákra"
|
||||
PythonTurtleHeading = "Visszaadja az aktuális irányt"
|
||||
PythonTurtleHideturtle = "A teknös elrejtése"
|
||||
PythonTurtleIsdown = "True-t válaszol ha a toll irás pozícióban van"
|
||||
PythonTurtleLeft = "a fokkot forduljon balra"
|
||||
PythonTurtlePendown = "Húzza le a tollat"
|
||||
PythonTurtlePensize = "Állítsa a vonalvastagságot x pixelre"
|
||||
PythonTurtlePenup = "Húzza fel a tollat"
|
||||
PythonTurtlePosition = "Az aktuális (x,y) pozíciót visszaadása"
|
||||
PythonTurtleReset = "Visszaállitani a rajzot (torléssel)"
|
||||
PythonTurtleRight = "a fokkot forduljon jobbra"
|
||||
PythonTurtleSetheading = "a fokokra állítja be az irányt"
|
||||
PythonTurtleShowturtle = "A teknöst meg mutatni"
|
||||
PythonTurtleSpeed = "Rajzolási sebesség 0 és 10 között"
|
||||
PythonTurtleWrite = "Szöveg irás"
|
||||
PythonUniform = "Lebegöpontos szám [a,b] -ban"
|
||||
PythonImportTime = "time modul importálása"
|
||||
PythonMonotonic = "Meg fordítani a monoton idö"
|
||||
PythonFileOpen = "Fájl megnyitása"
|
||||
PythonFileSeekable = "Seek-et lehete használni"
|
||||
PythonFileSeek = "A kurzort áthelyezni"
|
||||
PythonFileTell = "Visszaadja a kurzor helye"
|
||||
PythonFileClose = "Bezárni egy fájlt"
|
||||
PythonFileClosed = "True ha a fájl bezárva"
|
||||
PythonFileRead = "Olvas 16 bájtig"
|
||||
PythonFileWrite = "b-t irjon a fájlba"
|
||||
PythonFileReadline = "Olvas egy sort vagy 16 bájtig"
|
||||
PythonFileReadlines = "Olvas több sort"
|
||||
PythonFileTruncate = "A fájl átméretezése"
|
||||
PythonFileWritelines = "Irjon több sort"
|
||||
PythonFileName = "A fájl neve"
|
||||
PythonFileMode = "A fájl nyitott módja"
|
||||
PythonFileReadable = "read-et lehete használni"
|
||||
PythonFileWritable = "write-ot lehete használni"
|
||||
PythonImportOs = "os modul importálása"
|
||||
PythonOsUname = "Rendszer informaciók"
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Fájl törlése"
|
||||
PythonOsRename = "Fájl átnevezése"
|
||||
PythonOsListdir = "Fájlok listája"
|
||||
PythonImportSys = "sys modul importálása"
|
||||
PythonSysExit = "Terminate current program"
|
||||
PythonSysPrintexception = "Print exception"
|
||||
PythonSysByteorder = "The byte order of the system"
|
||||
PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
PythonKeyLeft = "BALRA NYÍL billentyű"
|
||||
PythonKeyUp = "FEL NYÍL billentyű"
|
||||
PythonKeyDown = "LE NYÍL billentyű"
|
||||
PythonKeyRight = "JOBBRA NYÍL billentyű"
|
||||
PythonKeyOk = "OK gomb"
|
||||
PythonKeyBack = "VISSZA gomb"
|
||||
PythonKeyHome = "Lakáskulcs"
|
||||
PythonKeyOnOff = "BE/KI gomb"
|
||||
PythonKeyShift = "SHIFT billentyű"
|
||||
PythonKeyAlpha = "ALPHA kulcs"
|
||||
PythonKeyXnt = "X,N,T gomb"
|
||||
PythonKeyVar = "VAR gomb"
|
||||
PythonKeyToolbox = "TOOLBOX gomb"
|
||||
PythonKeyBackspace = "BACKSPACE billentyű"
|
||||
PythonKeyExp = "EXPONENTIÁLIS kulcs"
|
||||
PythonKeyLn = "TERMÉSZETES LOGARITMUS kulcs"
|
||||
PythonKeyLog = "DECIMÁLIS LOGARITMUS billentyű"
|
||||
PythonKeyImaginary = "KÉPZELETES I kulcs"
|
||||
PythonKeyComma = "VESZSŰ gomb"
|
||||
PythonKeyPower = "POWER gomb"
|
||||
PythonKeySine = "SINE gomb"
|
||||
PythonKeyCosine = "KOSINUS kulcs"
|
||||
PythonKeyTangent = "ÉRINTŐ gomb"
|
||||
PythonKeyPi = "PI kulcs"
|
||||
PythonKeySqrt = "NÉGYGYÖK kulcs"
|
||||
PythonKeySquare = "SZÖGZET billentyű"
|
||||
PythonKeySeven = "7 kulcs"
|
||||
PythonKeyEight = "8 kulcs"
|
||||
PythonKeyNine = "9 kulcs"
|
||||
PythonKeyLeftParenthesis = "BAL ZÁRÓZELŐ gomb"
|
||||
PythonKeyRightParenthesis = "JOBB ZÁRÓZELŐ billentyű"
|
||||
PythonKeyFour = "4 kulcs"
|
||||
PythonKeyFive = "5 kulcs"
|
||||
PythonKeySix = "6 kulcs"
|
||||
PythonKeyMultiplication = "SZORZAT gomb"
|
||||
PythonKeyDivision = "OSZTÁS kulcs"
|
||||
PythonKeyOne = "1 kulcs"
|
||||
PythonKeyTwo = "2 kulcs"
|
||||
PythonKeyThree = "3 kulcs"
|
||||
PythonKeyPlus = "PLUSZ kulcs"
|
||||
PythonKeyMinus = "MÍNUS gomb"
|
||||
PythonKeyZero = "0 kulcs"
|
||||
PythonKeyDot = "DOT gomb"
|
||||
PythonKeyEe = "10 POWER X gomb"
|
||||
PythonKeyAns = "ANS kulcs"
|
||||
PythonKeyExe = "EXE kulcs"
|
||||
PythonImportUtils = "Az ulab.utils importálása"
|
||||
PythonUtilsFunction = "utils modul függvény előtagja"
|
||||
PythonTurtleBgcolor = "Módosítsa a háttérszínt"
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
PythonPound = "Commento"
|
||||
PythonPercent = "Modulo"
|
||||
PythonColon = "Due punti"
|
||||
PythonSemicon = "Punto e virgola"
|
||||
PythonExclamationMark = "Punto esclamativo"
|
||||
PythonLessThan = "Minore di"
|
||||
PythonGreaterThan = "Maggiore di"
|
||||
PythonQuestionMark = "Punto interrogativo"
|
||||
Python1J = "Unità immaginaria"
|
||||
PythonLF = "Nuova riga"
|
||||
PythonTab = "Tabulazione"
|
||||
@@ -25,13 +31,13 @@ PythonBin = "Converte un intero in binario"
|
||||
PythonCeil = "Parte intera superiore"
|
||||
PythonChoice = "Numero aleatorio nella lista"
|
||||
PythonClear = "Svuota la lista"
|
||||
PythonCmathFunction = "Funz. prefissata modulo cmath"
|
||||
PythonCmathFunction = "Prefisso funzione del modulo cmath"
|
||||
PythonColor = "Definisci un colore rvb"
|
||||
PythonColorBlack = "Colore nero"
|
||||
PythonColorBlue = "Colore blu"
|
||||
PythonColorBrown = "Colore marrone"
|
||||
PythonColorGray = "Colore grigio"
|
||||
PythonColorGreen = "Colore verde"
|
||||
PythonColorGrey = "Colore grigio"
|
||||
PythonColorOrange = "Colore arancione"
|
||||
PythonColorPink = "Colore rosa"
|
||||
PythonColorPurple = "Colore viola"
|
||||
@@ -45,19 +51,26 @@ PythonCosh = "Coseno iperbolico"
|
||||
PythonCount = "Conta le ricorrenze di x"
|
||||
PythonDegrees = "Conversione di radianti in gradi"
|
||||
PythonDivMod = "Quoziente e resto"
|
||||
PythonDrawCircle = "Disegnare un cerchio"
|
||||
PythonDrawLine = "Disegna una linea"
|
||||
PythonDrawString = "Visualizza il testo dal pixel x,y"
|
||||
PythonErf = "Funzione d'errore"
|
||||
PythonErfc = "Funzione d'errore complementare"
|
||||
PythonEval = "Valuta l'espressione nell'argomento "
|
||||
PythonExp = "Funzione esponenziale"
|
||||
PythonExpm1 = "Calcola exp(x)-1"
|
||||
PythonFactorial = "Fattoriale di x"
|
||||
PythonFabs = "Valore assoluto"
|
||||
PythonFillCircle = "Riempire un cerchio"
|
||||
PythonFillPolygon = "Riempire un poligono"
|
||||
PythonFillRect = "Riempie un rettangolo"
|
||||
PythonFloat = "Conversione in flottanti"
|
||||
PythonFloor = "Parte intera"
|
||||
PythonFmod = "a modulo b"
|
||||
PythonFrExp = "Mantissa ed esponente di x : (m,e)"
|
||||
PythonGamma = "Funzione gamma"
|
||||
PythonGetKeys = "Ottieni i tasti premuti"
|
||||
PythonGetPalette = "Ottieni la tavolozza del tema"
|
||||
PythonGetPixel = "Restituisce colore del pixel(x,y)"
|
||||
PythonGetrandbits = "Numero aleatorio con k bit"
|
||||
PythonGrid = "Attiva la visibilità della griglia"
|
||||
@@ -69,21 +82,37 @@ PythonImportKandinsky = "Importa modulo kandinsky"
|
||||
PythonImportRandom = "Importa modulo random"
|
||||
PythonImportMath = "Importa modulo math"
|
||||
PythonImportMatplotlibPyplot = "Importa modulo matplotlib.pyplot"
|
||||
PythonImportNumpy = "Importa modulo ulab.numpy"
|
||||
PythonImportScipy = "Importa modulo ulab.scipy"
|
||||
PythonImportTurtle = "Importa del modulo turtle"
|
||||
PythonImportTime = "Importa del modulo time"
|
||||
PythonImportOs = "Importa modulo os"
|
||||
PythonOsUname = "Ottieni informazioni sul sistema"
|
||||
PythonOsGetlogin = "Ottieni username"
|
||||
PythonOsRemove = "Rimuovere un file"
|
||||
PythonOsRename = "Rinomina file"
|
||||
PythonOsListdir = "Elenca file"
|
||||
PythonImportSys = "Importa modulo sys"
|
||||
PythonSysExit = "Termina programma corrente"
|
||||
PythonSysPrintexception = "Stampa eccezione"
|
||||
PythonSysByteorder = "Ordine di byte del sistema"
|
||||
PythonSysImplementation = "Informazioni su Python"
|
||||
PythonSysModules = "Dizionario dei moduli caricati"
|
||||
PythonSysVersion = "Versione linguaggio Python (stringa)"
|
||||
PythonSysVersioninfo = "Versione linguaggio Python (tupla)"
|
||||
PythonIndex = "Indice prima occorrenza di x"
|
||||
PythonInput = "Inserire un valore"
|
||||
PythonInsert = "Inserire x in posizione i-esima"
|
||||
PythonInt = "Conversione in intero"
|
||||
PythonIonFunction = "Prefisso di funzione modulo ion"
|
||||
PythonIsFinite = "Testa se x è finito"
|
||||
PythonIsInfinite = "Testa se x est infinito"
|
||||
PythonIsInfinite = "Testa se x è infinito"
|
||||
PythonIsKeyDown = "Restituisce True premendo tasto k"
|
||||
PythonBattery = "Restituisce la tensione della batteria"
|
||||
PythonBatteryLevel = "Restituisce il livello della batteria"
|
||||
PythonBatteryIscharging = "Restituisce se la batteria è in carica"
|
||||
PythonSetBrightness = "Imposta livello di luminosità"
|
||||
PythonGetBrightness = "Ottieni livello di luminosità"
|
||||
PythonIsNaN = "Testa se x è NaN"
|
||||
PythonKandinskyFunction = "Prefisso funzione modulo kandinsky"
|
||||
PythonKeyLeft = "Tasto FRECCIA SINISTRA"
|
||||
@@ -144,6 +173,14 @@ PythonMax = "Massimo"
|
||||
PythonMin = "Minimo"
|
||||
PythonModf = "Parti frazionarie e intere"
|
||||
PythonMonotonic = "Restituisce il valore dell'orologio"
|
||||
PythonNumpyFunction = "Prefisso modulo numpy"
|
||||
PythonNumpyFftFunction = "Prefisso modulo numpy.fft"
|
||||
PythonNumpyLinalgFunction = "Prefisso modulo numpy.linalg"
|
||||
PythonScipyFunction = "Prefisso modulo scipy"
|
||||
PythonScipyLinalgFunction = "Prefisso modulo scipy.linalg"
|
||||
PythonScipyOptimizeFunction = "Prefisso modulo scipy.optimize"
|
||||
PythonScipySignalFunction = "Prefisso modulo scipy.signal"
|
||||
PythonScipySpecialFunction = "Prefisso modulo scipy.special"
|
||||
PythonOct = "Conversione in ottale"
|
||||
PythonPhase = "Argomento di z"
|
||||
PythonPlot = "Disegna y in f. di x come linee"
|
||||
@@ -159,7 +196,7 @@ PythonRandrange = "Numero dentro il range(start, stop)"
|
||||
PythonRangeStartStop = "Lista da start a stop-1"
|
||||
PythonRangeStop = "Lista da 0 a stop-1"
|
||||
PythonRect = "Converte in coordinate algebriche"
|
||||
PythonRemove = "Cancella la prima x dalla lista"
|
||||
PythonRemove = "Cancella la prima x dalla lista"
|
||||
PythonReverse = "Inverte gli elementi della lista"
|
||||
PythonRound = "Arrotondato a n cifre decimali"
|
||||
PythonScatter = "Diagramma dispersione y in f. di x"
|
||||
@@ -169,6 +206,12 @@ PythonShow = "Mostra la figura"
|
||||
PythonSin = "Seno"
|
||||
PythonSinh = "Seno iperbolico"
|
||||
PythonSleep = "Sospende l'esecuzione t secondi"
|
||||
PythonLocalTime = "Converti il tempo in tuple"
|
||||
PythonMktime = "Converti tuple in tempo"
|
||||
PythonTime = "Ottieni il timestamp corrente"
|
||||
PythonSetLocaltime = "Imposta il tempo da una tupla"
|
||||
PythonRTCmode = "Ottieni la modalità RTC corrente"
|
||||
PythonSetRTCmode = "Imposta modalità RTC"
|
||||
PythonSort = "Ordina l'elenco"
|
||||
PythonSqrt = "Radice quadrata"
|
||||
PythonSum = "Somma degli elementi della lista"
|
||||
@@ -195,28 +238,28 @@ PythonTurtlePosition = "Fornisce posizione corrente (x,y)"
|
||||
PythonTurtleReset = "Azzera il disegno"
|
||||
PythonTurtleRight = "Ruota di a gradi a destra"
|
||||
PythonTurtleSetheading = "Imposta l'orientamento per a gradi"
|
||||
PythonTurtleSetposition = "Posiziona la tartaruga"
|
||||
PythonTurtleShowturtle = "Mostra la tartaruga"
|
||||
PythonTurtleSpeed = "Velocità di disegno (x tra 0 e 10)"
|
||||
PythonTurtleWrite = "Mostra un testo"
|
||||
PythonUniform = "Numero decimale tra [a,b]"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Wait for n second"
|
||||
PythonMonotonic = "Return monotonic time"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
PythonFileSeek = "Move file's cursor"
|
||||
PythonFileTell = "Get file's cursor location"
|
||||
PythonFileClose = "Closes a file"
|
||||
PythonFileClosed = "True if file was closed"
|
||||
PythonFileRead = "Read up to size bytes"
|
||||
PythonFileWrite = "Write b into file"
|
||||
PythonFileReadline = "Reads a line or up to size bytes"
|
||||
PythonFileReadlines = "Reads a list of lines"
|
||||
PythonFileTruncate = "Resize the file to size"
|
||||
PythonFileWritelines = "Writes a list of lines"
|
||||
PythonFileName = "Contains file's name"
|
||||
PythonFileMode = "Contains file's open mode"
|
||||
PythonFileReadable = "Tells if read can be used on a file"
|
||||
PythonFileWritable = "Tells if write can be used on a file"
|
||||
PythonImportTime = "Importa modulo time"
|
||||
PythonMonotonic = "Restituisce tempo monotonico"
|
||||
PythonFileOpen = "Apre un file"
|
||||
PythonFileSeekable = "Dice se si può usare il cursore su un file"
|
||||
PythonFileSeek = "Sposta cursore di un file"
|
||||
PythonFileTell = "Ottieni posizione del cursore del file"
|
||||
PythonFileClose = "Chiude un file"
|
||||
PythonFileClosed = "True se un file è stato chiuso"
|
||||
PythonFileRead = "Legge fino ai byte di un file"
|
||||
PythonFileWrite = "Scrive b in un file"
|
||||
PythonFileReadline = "Legge una riga o fino ai byte di un file"
|
||||
PythonFileReadlines = "Legge una lista di linee di un file"
|
||||
PythonFileTruncate = "Ridimensiona il file"
|
||||
PythonFileWritelines = "Scrive una lista di linee su file"
|
||||
PythonFileName = "Contiene il nome del file"
|
||||
PythonFileMode = "Contiene la modalità di apertura del file"
|
||||
PythonFileReadable = "Dice se si può leggere sul file"
|
||||
PythonFileWritable = "Dice se si può scrivere sul file"
|
||||
PythonImportUtils = "Importazione di ulab.utils"
|
||||
PythonUtilsFunction = "Prefisso funzione del modulo utils"
|
||||
PythonTurtleBgcolor = "Cambia il colore dello sfondo"
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
PythonPound = "Opmerkingen"
|
||||
PythonPercent = "Modulo"
|
||||
PythonColon = "Dubbele punt"
|
||||
PythonSemicon = "Puntkomma"
|
||||
PythonExclamationMark = "Uitroepteken"
|
||||
PythonLessThan = "Kleiner dan"
|
||||
PythonGreaterThan = "Groter dan"
|
||||
PythonQuestionMark = "Vraagteken"
|
||||
Python1J = "Imaginaire i"
|
||||
PythonLF = "Nieuwe regel"
|
||||
PythonTab = "Tabulatie"
|
||||
@@ -13,14 +19,14 @@ PythonAbs = "Absolute waarde"
|
||||
PythonAcos = "Arccosinus"
|
||||
PythonAcosh = "Arccosinus hyperbolicus"
|
||||
PythonAppend = "Voeg x toe aan het eind van je lijst"
|
||||
PythonArrow = "Arrow from (x,y) to (x+dx,y+dy)"
|
||||
PythonArrow = "Pijl van (x,y) naar (x+dx,y+dy)"
|
||||
PythonAsin = "Arcsinus"
|
||||
PythonAsinh = "Arcsinus hyperbolicus"
|
||||
PythonAtan = "Arctangens"
|
||||
PythonAtan2 = "Geeft atan(y/x)"
|
||||
PythonAtanh = "Arctangens hyperbolicus"
|
||||
PythonAxis = "Set the axes to (xmin,xmax,ymin,ymax)"
|
||||
PythonBar = "Draw a bar plot with x values"
|
||||
PythonAxis = "Stel de assen in (xmin,xmax,ymin,ymax)"
|
||||
PythonBar = "Teken staafdiagram met x-waarden"
|
||||
PythonBin = "Zet integer om in een binair getal"
|
||||
PythonCeil = "Plafond"
|
||||
PythonChoice = "Geeft willek. getal van de lijst"
|
||||
@@ -30,8 +36,8 @@ PythonColor = "Definieer een rgb kleur"
|
||||
PythonColorBlack = "Zwarte kleur"
|
||||
PythonColorBlue = "Blauwe kleur"
|
||||
PythonColorBrown = "Bruine kleur"
|
||||
PythonColorGray = "Grijze kleur"
|
||||
PythonColorGreen = "Groene kleur"
|
||||
PythonColorGrey = "Grijze kleur"
|
||||
PythonColorOrange = "Oranje kleur"
|
||||
PythonColorPink = "Roze kleur"
|
||||
PythonColorPurple = "Paarse kleur"
|
||||
@@ -45,36 +51,55 @@ PythonCosh = "Cosinus hyperbolicus"
|
||||
PythonCount = "Tel voorkomen van x"
|
||||
PythonDegrees = "Zet x om van radialen naar graden"
|
||||
PythonDivMod = "Quotiënt en rest"
|
||||
PythonDrawCircle = "Teken een cirkel"
|
||||
PythonDrawLine = "Teken een lijn"
|
||||
PythonDrawString = "Geef een tekst weer van pixel (x,y)"
|
||||
PythonErf = "Error functie"
|
||||
PythonErfc = "Complementaire error functie"
|
||||
PythonEval = "Geef de geëvalueerde uitdrukking"
|
||||
PythonExp = "Exponentiële functie"
|
||||
PythonExpm1 = "Bereken exp(x)-1"
|
||||
PythonFactorial = "faculteit van x"
|
||||
PythonFabs = "Absolute waarde"
|
||||
PythonFillCircle = "Vul een cirkel"
|
||||
PythonFillPolygon = "Vul een veelhoek"
|
||||
PythonFillRect = "Vul een rechthoek bij pixel (x,y)"
|
||||
PythonFloat = "Zet x om in een float"
|
||||
PythonFloor = "Vloer"
|
||||
PythonFmod = "a modulo b"
|
||||
PythonFrExp = "Mantisse en exponent van x: (m,e)"
|
||||
PythonGamma = "Gammafunctie"
|
||||
PythonGetKeys = "Get toetsen ingedrukt"
|
||||
PythonGetPalette = "Thema palet krijgen"
|
||||
PythonGetPixel = "Geef pixel (x,y) kleur (rgb)"
|
||||
PythonGetrandbits = "Integer met k willekeurige bits"
|
||||
PythonGrid = "Toggle the visibility of the grid"
|
||||
PythonGrid = "Verander zichtbaarheid raster"
|
||||
PythonHex = "Zet integer om in hexadecimaal"
|
||||
PythonHist = "Draw the histogram of x"
|
||||
PythonHist = "Teken het histogram van x"
|
||||
PythonImportCmath = "Importeer cmath module"
|
||||
PythonImportIon = "Importeer ion module"
|
||||
PythonImportKandinsky = "Importeer kandinsky module"
|
||||
PythonImportRandom = "Importeer random module"
|
||||
PythonImportMath = "Importeer math module"
|
||||
PythonImportMatplotlibPyplot = "Import matplotlib.pyplot module"
|
||||
PythonImportMatplotlibPyplot = "Importeer matplotlib.pyplot module"
|
||||
PythonImportNumpy = "Importeer ulab.numpy module"
|
||||
PythonImportScipy = "Importeer ulab.scipy module"
|
||||
PythonImportTime = "Importeer time module"
|
||||
PythonImportOs = "Importeer os module"
|
||||
PythonOsUname = " Krijg systeeminfo"
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Een bestand verwijderen"
|
||||
PythonOsRename = "Hernoem bestand"
|
||||
PythonOsListdir = "Lijstbestanden"
|
||||
PythonImportSys = "Importeer sys module"
|
||||
PythonImportSys = "Importeer sys module"
|
||||
PythonSysExit = "Terminate current program"
|
||||
PythonSysPrintexception = "Print exception"
|
||||
PythonSysByteorder = "The byte order of the system"
|
||||
PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
PythonImportTurtle = "Importeer turtle module"
|
||||
PythonIndex = "Index van de eerste x aanwezigheden"
|
||||
PythonInput = "Wijs een waarde toe"
|
||||
@@ -84,7 +109,12 @@ PythonIonFunction = "ion module voorvoegsel"
|
||||
PythonIsFinite = "Controleer of x eindig is"
|
||||
PythonIsInfinite = "Controleer of x oneindig is"
|
||||
PythonIsKeyDown = "Geef True als k toets omlaag is"
|
||||
PythonIsNaN = "Controleer of x geen nummer is"
|
||||
PythonBattery = "Return batterijspanning"
|
||||
PythonBatteryLevel = "Batterijniveau teruggeven"
|
||||
PythonBatteryIscharging = "Keer terug als de batterij wordt opgeladen"
|
||||
PythonSetBrightness = "Set brightness level"
|
||||
PythonGetBrightness = "Get brightness level"
|
||||
PythonIsNaN = "Controleer of x geen getal is"
|
||||
PythonKandinskyFunction = "kandinsky module voorvoegsel"
|
||||
PythonKeyLeft = "PIJL NAAR LINKS toets"
|
||||
PythonKeyUp = "PIJL OMHOOG toets"
|
||||
@@ -144,16 +174,24 @@ PythonMax = "Maximum"
|
||||
PythonMin = "Minimum"
|
||||
PythonModf = "Fractionele en gehele delen van x"
|
||||
PythonMonotonic = "Waarde van een monotone klok"
|
||||
PythonNumpyFunction = "numpy module prefix"
|
||||
PythonNumpyFftFunction = "numpy.fft module prefix"
|
||||
PythonNumpyLinalgFunction = "numpy.linalg module prefix"
|
||||
PythonScipyFunction = "scipy module prefix"
|
||||
PythonScipyLinalgFunction = "scipy.linalg module prefix"
|
||||
PythonScipyOptimizeFunction = "scipy.optimize module prefix"
|
||||
PythonScipySignalFunction = "scipy.signal module prefix"
|
||||
PythonScipySpecialFunction = "scipy.special module prefix"
|
||||
PythonOct = "Integer omzetten naar octaal"
|
||||
PythonPhase = "Fase van z in radialen"
|
||||
PythonPlot = "Plot y versus x as lines"
|
||||
PythonPlot = "Plot y versus x als lijnen"
|
||||
PythonPolar = "z in poolcoördinaten"
|
||||
PythonPop = "Verwijder en breng het laatste item terug"
|
||||
PythonPower = "x tot de macht y"
|
||||
PythonPrint = "Print object"
|
||||
PythonRadians = "Zet x om van graden naar radialen"
|
||||
PythonRandint = "Geeft willek. integer in [a,b]"
|
||||
PythonRandom = "Een willekeurig getal in [0,1["
|
||||
PythonRandom = "Een willekeurig getal in [0,1)"
|
||||
PythonRandomFunction = "random module voorvoegsel"
|
||||
PythonRandrange = "Willek. getal in range(start, stop)"
|
||||
PythonRangeStartStop = "Lijst van start tot stop-1"
|
||||
@@ -162,19 +200,25 @@ PythonRect = "z in cartesiaanse coördinaten"
|
||||
PythonRemove = "Verwijder het eerste voorkomen van x"
|
||||
PythonReverse = "Keer de elementen van de lijst om"
|
||||
PythonRound = "Rond af op n cijfers"
|
||||
PythonScatter = "Draw a scatter plot of y versus x"
|
||||
PythonScatter = "Teken scatterplot van y versus x"
|
||||
PythonSeed = "Start willek. getallengenerator"
|
||||
PythonSetPixel = "Kleur pixel (x,y)"
|
||||
PythonShow = "Display the figure"
|
||||
PythonSin= "Sinus"
|
||||
PythonShow = "Figuur weergeven"
|
||||
PythonSin = "Sinus"
|
||||
PythonSinh = "Sinus hyperbolicus"
|
||||
PythonSleep = "Stel executie voor t seconden uit"
|
||||
PythonLocalTime = "Zet tijd om in tuple"
|
||||
PythonMktime = "Tuple omzetten in tijd"
|
||||
PythonTime = "Haal de huidige tijdstempel"
|
||||
PythonSetLocaltime = "Stel de tijd in vanaf een tuple"
|
||||
PythonRTCmode = "Huidige RTC-modus kregen"
|
||||
PythonSetRTCmode = "RTC-modus instellen"
|
||||
PythonSort = "Sorteer de lijst"
|
||||
PythonSqrt = "Vierkantswortel"
|
||||
PythonSum = "Sommeer de items van een lijst"
|
||||
PythonTan = "Tangens"
|
||||
PythonTanh = "Tangens hyperbolicus"
|
||||
PythonText = "Display a text at (x,y) coordinates"
|
||||
PythonText = "Geef tekst weer op coördinaten (x,y)"
|
||||
PythonTimeFunction = "time module voorvoegsel"
|
||||
PythonTrunc = "x afgeknot tot een integer"
|
||||
PythonTurtleBackward = "Ga achterwaarts met x pixels"
|
||||
@@ -195,14 +239,11 @@ PythonTurtlePosition = "Zet huidige (x,y) locatie terug"
|
||||
PythonTurtleReset = "Reset de tekening"
|
||||
PythonTurtleRight = "Ga rechtsaf met a graden"
|
||||
PythonTurtleSetheading = "Zet de oriëntatie op a graden"
|
||||
PythonTurtleSetposition = "Plaats de schildpad"
|
||||
PythonTurtleShowturtle = "Laat de schildpad zien"
|
||||
PythonTurtleSpeed = "Tekensnelheid tussen 0 and 10"
|
||||
PythonTurtleWrite = "Display a text"
|
||||
PythonUniform = "Zwevendekommagetal in [a,b]"
|
||||
PythonUniform = "Decimaal getal in [a,b]"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Wait for n second"
|
||||
PythonMonotonic = "Return monotonic time"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
@@ -220,3 +261,6 @@ PythonFileName = "Contains file's name"
|
||||
PythonFileMode = "Contains file's open mode"
|
||||
PythonFileReadable = "Tells if read can be used on a file"
|
||||
PythonFileWritable = "Tells if write can be used on a file"
|
||||
PythonImportUtils = "Ulab.utils importeren"
|
||||
PythonUtilsFunction = "utils module functie prefix"
|
||||
PythonTurtleBgcolor = "Verander de achtergrondkleur"
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
PythonPound = "Comentário"
|
||||
PythonPercent = "Módulo"
|
||||
PythonColon = "Dois pontos"
|
||||
PythonSemicon = "Ponto e vírgula"
|
||||
PythonExclamationMark = "Ponto de exclamação"
|
||||
PythonLessThan = "Menor que"
|
||||
PythonGreaterThan = "Maior que"
|
||||
PythonQuestionMark = "Ponto de interrogação"
|
||||
Python1J = "i Complexo"
|
||||
PythonLF = "Nova linha"
|
||||
PythonTab = "Tabulação"
|
||||
@@ -30,8 +36,8 @@ PythonColor = "Define uma cor rgb"
|
||||
PythonColorBlack = "Cor preta"
|
||||
PythonColorBlue = "Cor azul"
|
||||
PythonColorBrown = "Cor castanha"
|
||||
PythonColorGray = "Cor cinzenta"
|
||||
PythonColorGreen = "Cor verde"
|
||||
PythonColorGrey = "Cor cinzenta"
|
||||
PythonColorOrange = "Cor laranja"
|
||||
PythonColorPink = "Cor rosa"
|
||||
PythonColorPurple = "Cor roxa"
|
||||
@@ -45,19 +51,26 @@ PythonCosh = "Cosseno hiperbólico"
|
||||
PythonCount = "Contar as ocorrências de x"
|
||||
PythonDegrees = "Converter x de radianos para graus"
|
||||
PythonDivMod = "Quociente e resto"
|
||||
PythonDrawCircle = "Desenha um círculo"
|
||||
PythonDrawLine = "Desenhe uma linha"
|
||||
PythonDrawString = "Mostrar o texto do pixel (x,y)"
|
||||
PythonErf = "Função erro"
|
||||
PythonErfc = "Função erro complementar"
|
||||
PythonEval = "Devolve a expressão avaliada"
|
||||
PythonExp = "Função exponencial"
|
||||
PythonExpm1 = "Calcular exp(x)-1"
|
||||
PythonFactorial = "Fatorial de x"
|
||||
PythonFabs = "Valor absoluto"
|
||||
PythonFillCircle = "Preencher um círculo"
|
||||
PythonFillPolygon = "Preencher um polígono"
|
||||
PythonFillRect = "Preencher um retângulo em (x,y)"
|
||||
PythonFloat = "Converter x num flutuante"
|
||||
PythonFloor = "Parte inteira"
|
||||
PythonFmod = "a módulo b"
|
||||
PythonFrExp = "Coeficiente e expoente de x: (m, e)"
|
||||
PythonGamma = "Função gama"
|
||||
PythonGetKeys = "Obter teclas pressionadas"
|
||||
PythonGetPalette = "Obter paleta temática"
|
||||
PythonGetPixel = "Devolve a cor do pixel (x,y)"
|
||||
PythonGetrandbits = "Número inteiro aleatório com k bits"
|
||||
PythonGrid = "Alterar visibilidade da grelha"
|
||||
@@ -69,6 +82,8 @@ PythonImportKandinsky = "Importar módulo kandinsky"
|
||||
PythonImportRandom = "Importar módulo random"
|
||||
PythonImportMath = "Importar módulo math"
|
||||
PythonImportMatplotlibPyplot = "Importar módulo matplotlib.pyplot"
|
||||
PythonImportNumpy = "Importar módulo ulab.numpy"
|
||||
PythonImportScipy = "Importar módulo ulab.scipy"
|
||||
PythonImportTime = "Importar módulo time"
|
||||
PythonImportTurtle = "Importar módulo turtle"
|
||||
PythonIndex = "Índice da primeira ocorrência de x"
|
||||
@@ -79,6 +94,11 @@ PythonIonFunction = "Prefixo da função do módulo ion"
|
||||
PythonIsFinite = "Verificar se x é finito"
|
||||
PythonIsInfinite = "Verificar se x é infinito"
|
||||
PythonIsKeyDown = "Devolve True se tecla k pressionada"
|
||||
PythonBattery = "Retornar a voltagem da bateria"
|
||||
PythonBatteryLevel = "Retornar nível de bateria"
|
||||
PythonBatteryIscharging = "Retorne se a bateria estiver carregando"
|
||||
PythonSetBrightness = "Definir nível de brilho"
|
||||
PythonGetBrightness = "Obter nível de brilho"
|
||||
PythonIsNaN = "Verificar se x é um NaN"
|
||||
PythonKandinskyFunction = "Prefixo da função do módulo kandinsky"
|
||||
PythonKeyLeft = "tecla SETA ESQUERDA"
|
||||
@@ -139,6 +159,14 @@ PythonMax = "Máximo"
|
||||
PythonMin = "Mínimo"
|
||||
PythonModf = "Partes inteira e frácionária de x"
|
||||
PythonMonotonic = "Devolve o valor do relógio"
|
||||
PythonNumpyFunction = "Prefixo do módulo numpy"
|
||||
PythonNumpyFftFunction = "Prefixo do módulo numpy.fft"
|
||||
PythonNumpyLinalgFunction = "Prefixo do módulo numpy.linalg"
|
||||
PythonScipyFunction = "Prefixo do módulo scipy"
|
||||
PythonScipyLinalgFunction = "Prefixo do módulo scipy.linalg"
|
||||
PythonScipyOptimizeFunction = "Prefixo do módulo scipy.optimize"
|
||||
PythonScipySignalFunction = "Prefixo do módulo scipy.signal"
|
||||
PythonScipySpecialFunction = "Prefixo do módulo scipy.special"
|
||||
PythonOct = "Converter número inteiro em octal"
|
||||
PythonPhase = "Argumento de z"
|
||||
PythonPlot = "Desenhar y em função de x"
|
||||
@@ -164,6 +192,12 @@ PythonShow = "Mostrar a figura"
|
||||
PythonSin = "Seno"
|
||||
PythonSinh = "Seno hiperbólico"
|
||||
PythonSleep = "Suspender a execução por t segundos"
|
||||
PythonLocalTime = "Convert o tempo em tupla"
|
||||
PythonMktime = "Convert tuple em tempo"
|
||||
PythonTime = "Obter o estamp de tempo atual"
|
||||
PythonSetLocaltime = "Definir tempo a partir de uma tupla"
|
||||
PythonRTCmode = "Obter o modo RTC atual"
|
||||
PythonSetRTCmode = "Definir o modo RTC"
|
||||
PythonSort = "Ordenar a lista"
|
||||
PythonSqrt = "Raiz quadrada"
|
||||
PythonSum = "Soma dos itens da lista"
|
||||
@@ -190,7 +224,6 @@ PythonTurtlePosition = "Devolve a posição atual (x,y)"
|
||||
PythonTurtleReset = "Reiniciar o desenho"
|
||||
PythonTurtleRight = "Virar à esquerda por a graus"
|
||||
PythonTurtleSetheading = "Definir a orientação por a graus"
|
||||
PythonTurtleSetposition = "Positionne la tortue"
|
||||
PythonTurtleShowturtle = "Mostrar o turtle"
|
||||
PythonTurtleSpeed = "Velocidade do desenho entre 0 e 10"
|
||||
PythonTurtleWrite = "Mostrar um texto"
|
||||
@@ -198,11 +231,18 @@ PythonUniform = "Número decimal em [a,b]"
|
||||
PythonImportTime = "Import time module"
|
||||
PythonImportOs = "Import os module"
|
||||
PythonOsUname = " Obter informações do sistema"
|
||||
PythonOsGetlogin = "Get username"
|
||||
PythonOsRemove = "Remover um ficheiro"
|
||||
PythonOsRename = "Renomear ficheiro"
|
||||
PythonOsListdir = "Listar ficheiros"
|
||||
PythonTimePrefix = "time module function prefix"
|
||||
PythonTimeSleep = "Wait for n second"
|
||||
PythonImportSys = "Import sys module"
|
||||
PythonSysExit = "Terminate current program"
|
||||
PythonSysPrintexception = "Print exception"
|
||||
PythonSysByteorder = "The byte order of the system"
|
||||
PythonSysImplementation = "Information about Python"
|
||||
PythonSysModules = "Dictionary of loaded modules"
|
||||
PythonSysVersion = "Python language version (string)"
|
||||
PythonSysVersioninfo = "Python language version (tuple)"
|
||||
PythonMonotonic = "Return monotonic time"
|
||||
PythonFileOpen = "Opens a file"
|
||||
PythonFileSeekable = "Tells if seek can be used on a file"
|
||||
@@ -220,3 +260,6 @@ PythonFileName = "Contains file's name"
|
||||
PythonFileMode = "Contains file's open mode"
|
||||
PythonFileReadable = "Tells if read can be used on a file"
|
||||
PythonFileWritable = "Tells if write can be used on a file"
|
||||
PythonImportUtils = "Importando ulab.utils"
|
||||
PythonUtilsFunction = "prefixo de função do módulo utils"
|
||||
PythonTurtleBgcolor = "Alterar a cor de fundo"
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
PythonCommandAmpersand = "&"
|
||||
PythonCommandLF = "\\n"
|
||||
PythonCommandPercent = "%"
|
||||
PythonCommandColon = ":"
|
||||
PythonCommandSemicon = ";"
|
||||
PythonCommandExclamationMark = "!"
|
||||
PythonCommandLessThan = "<"
|
||||
PythonCommandGreaterThan = ">"
|
||||
PythonCommandQuestionMark = "?"
|
||||
PythonCommandPound = "#"
|
||||
PythonCommandSingleQuote = "'x'"
|
||||
PythonCommandSymbolExp = "^"
|
||||
@@ -32,8 +38,8 @@ PythonCommandColor = "color(r,g,b)"
|
||||
PythonCommandColorBlack = "'black'"
|
||||
PythonCommandColorBlue = "'blue'"
|
||||
PythonCommandColorBrown = "'brown'"
|
||||
PythonCommandColorGray = "'gray'"
|
||||
PythonCommandColorGreen = "'green'"
|
||||
PythonCommandColorGrey = "'grey'"
|
||||
PythonCommandColorOrange = "'orange'"
|
||||
PythonCommandColorPink = "'pink'"
|
||||
PythonCommandColorPurple = "'purple'"
|
||||
@@ -50,6 +56,8 @@ PythonCommandCount = "list.count(x)"
|
||||
PythonCommandCountWithoutArg = ".count(\x11)"
|
||||
PythonCommandDegrees = "degrees(x)"
|
||||
PythonCommandDivMod = "divmod(a,b)"
|
||||
PythonCommandDrawCircle = "draw_circle(x,y,r,color)"
|
||||
PythonCommandDrawLine = "draw_line(x1,y1,x2,y2,color)"
|
||||
PythonCommandDrawString = "draw_string(\"text\",x,y)"
|
||||
PythonCommandConstantE = "e"
|
||||
PythonCommandErf = "erf(x)"
|
||||
@@ -58,13 +66,18 @@ PythonCommandEval = "eval(\"expression\")"
|
||||
PythonCommandExp = "exp(x)"
|
||||
PythonCommandExpComplex = "exp(z)"
|
||||
PythonCommandExpm1 = "expm1(x)"
|
||||
PythonCommandFactorial = "factorial(x)"
|
||||
PythonCommandFabs = "fabs(x)"
|
||||
PythonCommandFillCircle = "fill_circle(x,y,r,color)"
|
||||
PythonCommandFillPolygon = "fill_polygon([(x1,y1),...],color)"
|
||||
PythonCommandFillRect = "fill_rect(x,y,width,height,color)"
|
||||
PythonCommandFloat = "float(x)"
|
||||
PythonCommandFloor = "floor(x)"
|
||||
PythonCommandFmod = "fmod(a,b)"
|
||||
PythonCommandFrExp = "frexp(x)"
|
||||
PythonCommandGamma = "gamma(x)"
|
||||
PythonCommandGetKeys = "get_keys()"
|
||||
PythonCommandGetPalette = "get_palette()"
|
||||
PythonCommandGetPixel = "get_pixel(x,y)"
|
||||
PythonCommandGetrandbits = "getrandbits(k)"
|
||||
PythonCommandGrid = "grid()"
|
||||
@@ -85,9 +98,13 @@ PythonCommandImportIon = "import ion"
|
||||
PythonCommandImportKandinsky = "import kandinsky"
|
||||
PythonCommandImportMath = "import math"
|
||||
PythonCommandImportMatplotlibPyplot = "import matplotlib.pyplot"
|
||||
PythonCommandImportFromNumpy = "from ulab import numpy as np"
|
||||
PythonCommandImportFromScipy = "from ulab import scipy as spy"
|
||||
PythonCommandImportRandom = "import random"
|
||||
PythonCommandImportOs = "import os"
|
||||
PythonCommandImportFromOs = "from os import *"
|
||||
PythonCommandImportSys = "import sys"
|
||||
PythonCommandImportFromSys = "from sys import *"
|
||||
PythonCommandImportTime = "import time"
|
||||
PythonCommandImportTurtle = "import turtle"
|
||||
PythonCommandIndex = "list.index(x)"
|
||||
@@ -150,6 +167,11 @@ PythonCommandKeyEe = "KEY_EE"
|
||||
PythonCommandKeyAns = "KEY_ANS"
|
||||
PythonCommandKeyExe = "KEY_EXE"
|
||||
PythonCommandIsKeyDown = "keydown(k)"
|
||||
PythonCommandBattery = "battery()"
|
||||
PythonCommandBatteryLevel = "battery_level()"
|
||||
PythonCommandBatteryIscharging = "battery_ischarging()"
|
||||
PythonCommandSetBrightness = "set_brightness()"
|
||||
PythonCommandGetBrightness = "get_brightness()"
|
||||
PythonCommandLdexp = "ldexp(x,i)"
|
||||
PythonCommandLength = "len(object)"
|
||||
PythonCommandLgamma = "lgamma(x)"
|
||||
@@ -165,6 +187,128 @@ PythonCommandMax = "max(list)"
|
||||
PythonCommandMin = "min(list)"
|
||||
PythonCommandModf = "modf(x)"
|
||||
PythonCommandMonotonic = "monotonic()"
|
||||
PythonCommandNumpyArray = "np.array(a)"
|
||||
PythonCommandNumpyArange = "np.arange(i)"
|
||||
PythonCommandNumpyConcatenate = "np.concatenate(a,b)"
|
||||
PythonCommandNumpyDiag = "np.diag(a)"
|
||||
PythonCommandNumpyZeros = "np.zeros(s)"
|
||||
PythonCommandNumpyOnes = "np.ones(s)"
|
||||
PythonCommandNumpyEmpty = "np.empty(s)"
|
||||
PythonCommandNumpyEye = "np.eye(n, m)"
|
||||
PythonCommandNumpyFull = "np.full(s, v)"
|
||||
PythonCommandNumpyLinspace = "np.linspace(s, e)"
|
||||
PythonCommandNumpyLogspace = "np.logspace(s, e)"
|
||||
PythonCommandNumpyCopy = "ndarray.copy()"
|
||||
PythonCommandNumpyCopyWithoutArg = ".copy()"
|
||||
PythonCommandNumpyDtype = "ndarray.dtype"
|
||||
PythonCommandNumpyDtypeWithoutArg = ".dtype"
|
||||
PythonCommandNumpyFlat = "ndarray.flat"
|
||||
PythonCommandNumpyFlatWithoutArg = ".flat"
|
||||
PythonCommandNumpyFlatten = "ndarray.flatten()"
|
||||
PythonCommandNumpyFlattenWithoutArg = ".flatten()"
|
||||
PythonCommandNumpyShape = "ndarray.shape"
|
||||
PythonCommandNumpyShapeWithoutArg = ".shape"
|
||||
PythonCommandNumpyReshape = "ndarray.reshape(s)"
|
||||
PythonCommandNumpyReshapeWithoutArg = ".reshape(\x11)"
|
||||
PythonCommandNumpySize = "ndarray.size"
|
||||
PythonCommandNumpySizeWithoutArg = ".size"
|
||||
PythonCommandNumpyTranspose = "ndarray.transpose()"
|
||||
PythonCommandNumpyTransposeWithoutArg = ".transpose()"
|
||||
PythonCommandNumpySort = "ndarray.sort()"
|
||||
PythonCommandNumpySortWithoutArg = ".sort()"
|
||||
PythonCommandNumpyFromBuffer = "ndarray.frombuffer(b)"
|
||||
PythonCommandNumpyToBytes = "ndarray.tobytes()"
|
||||
PythonCommandNumpyToBytesWithoutArg = ".tobytes()"
|
||||
PythonCommandNumpySetPrintOptions = "np.set_printoptions()"
|
||||
PythonCommandNumpyGetPrintOptions = "np.get_printoptions()"
|
||||
PythonCommandNumpyNdinfo = "np.ndinfo(a)"
|
||||
PythonCommandNumpyAll = "np.all(a)"
|
||||
PythonCommandNumpyAny = "np.any(a)"
|
||||
PythonCommandNumpyArgmax = "np.argmax(a)"
|
||||
PythonCommandNumpyArgmin = "np.argmin(a)"
|
||||
PythonCommandNumpyArgsort = "np.argsort(a)"
|
||||
PythonCommandNumpyClip = "np.clip(a, min, max)"
|
||||
PythonCommandNumpyConvolve = "np.convolve(a, b)"
|
||||
PythonCommandNumpyDiff = "np.diff(a)"
|
||||
PythonCommandNumpyInterp = "np.interp(a)"
|
||||
PythonCommandNumpyDot = "np.dot(a, b)"
|
||||
PythonCommandNumpyCross = "np.cross(a, b)"
|
||||
PythonCommandNumpyEqual = "np.equal(a, b)"
|
||||
PythonCommandNumpyNot_equal = "np.not_equal(a, b)"
|
||||
PythonCommandNumpyFlip = "np.flip(a)"
|
||||
PythonCommandNumpyIsfinite = "np.isfinite(a)"
|
||||
PythonCommandNumpyIsinf = "np.isinf(a)"
|
||||
PythonCommandNumpyMean = "np.mean(a)"
|
||||
PythonCommandNumpyMin = "np.min(a)"
|
||||
PythonCommandNumpyMax = "np.max(a)"
|
||||
PythonCommandNumpyMedian = "np.median(a)"
|
||||
PythonCommandNumpyMinimum = "np.minimum(a, b)"
|
||||
PythonCommandNumpyMaximum = "np.maximum(a, b)"
|
||||
PythonCommandNumpyPolyfit = "np.polyfit(a, b, y)"
|
||||
PythonCommandNumpyPolyval = "np.polyval(p, x)"
|
||||
PythonCommandNumpyRoll = "np.roll(a, n)"
|
||||
PythonCommandNumpySortWithArguments = "np.sort(a)"
|
||||
PythonCommandNumpyStd = "np.std(a)"
|
||||
PythonCommandNumpySum = "np.sum(a)"
|
||||
PythonCommandNumpyTrace = "np.trace(a)"
|
||||
PythonCommandNumpyTrapz = "np.trapz(y)"
|
||||
PythonCommandNumpyWhere = "np.where(c, x, y)"
|
||||
PythonCommandNumpyVectorize = "np.vectorize(f)"
|
||||
PythonCommandNumpyAcos = "np.acos(a)"
|
||||
PythonCommandNumpyAcosh = "np.acosh(a)"
|
||||
PythonCommandNumpyArctan2 = "np.arctan2(a)"
|
||||
PythonCommandNumpyAround = "np.around(a)"
|
||||
PythonCommandNumpyAsin = "np.asin(a)"
|
||||
PythonCommandNumpyAsinh = "np.asinh(a)"
|
||||
PythonCommandNumpyAtan = "np.atan(a)"
|
||||
PythonCommandNumpyAtanh = "np.atanh(a)"
|
||||
PythonCommandNumpyCeil = "np.ceil(a)"
|
||||
PythonCommandNumpyCos = "np.cos(a)"
|
||||
PythonCommandNumpyCosh = "np.cosh(a)"
|
||||
PythonCommandNumpyDegrees = "np.degrees(a)"
|
||||
PythonCommandNumpyExp = "np.exp(a)"
|
||||
PythonCommandNumpyExpm1 = "np.expm1(a)"
|
||||
PythonCommandNumpyFloor = "np.floor(a)"
|
||||
PythonCommandNumpyLog = "np.log(a)"
|
||||
PythonCommandNumpyLog10 = "np.log10(a)"
|
||||
PythonCommandNumpyLog2 = "np.log2(a)"
|
||||
PythonCommandNumpyRadians = "np.radians(a)"
|
||||
PythonCommandNumpySin = "np.sin(a)"
|
||||
PythonCommandNumpySinh = "np.sinh(a)"
|
||||
PythonCommandNumpySqrt = "np.sqrt(a)"
|
||||
PythonCommandNumpyTan = "np.tan(a)"
|
||||
PythonCommandNumpyTanh = "np.tanh(a)"
|
||||
PythonCommandNumpyBool = "np.bool"
|
||||
PythonCommandNumpyFloat = "np.float"
|
||||
PythonCommandNumpyUint8 = "np.uint8"
|
||||
PythonCommandNumpyInt8 = "np.int8"
|
||||
PythonCommandNumpyUint16 = "np.uint16"
|
||||
PythonCommandNumpyInt16 = "np.int16"
|
||||
PythonCommandNumpyNan = "np.nan"
|
||||
PythonCommandNumpyInf = "np.inf"
|
||||
PythonCommandNumpyE = "np.e"
|
||||
PythonCommandNumpyPi = "np.pi"
|
||||
PythonCommandNumpyFft = "np.fft.fft(a)"
|
||||
PythonCommandNumpyIfft = "np.fft.ifft(a)"
|
||||
PythonCommandNumpyDet = "np.linalg.det(a)"
|
||||
PythonCommandNumpyEig = "np.linalg.eig(a)"
|
||||
PythonCommandNumpyCholesky = "np.linalg.cholesky(a)"
|
||||
PythonCommandNumpyInv = "np.linalg.inv(a)"
|
||||
PythonCommandNumpyNorm = "np.linalg.norm(a)"
|
||||
PythonCommandNumpyFunction = "np.function"
|
||||
PythonCommandNumpyFunctionWithoutArg = "np.\x11"
|
||||
PythonCommandNumpyFftFunction = "np.fft.function"
|
||||
PythonCommandNumpyFftFunctionWithoutArg = "np.fft.\x11"
|
||||
PythonCommandNumpyLinalgFunction = "np.linalg.function"
|
||||
PythonCommandNumpyLinalgFunctionWithoutArg = "np.linalg.\x11"
|
||||
PythonCommandImportFromUtils = "from ulab import utils"
|
||||
PythonCommandUtilsFunction = "utils.function"
|
||||
PythonCommandUtilsFunctionWithoutArg = "utils.\x11"
|
||||
PythonCommandUtilsSpectrogram = "spectrogram(a)"
|
||||
PythonCommandUtilsFromInt16Buffer = "from_int16_buffer(b)"
|
||||
PythonCommandUtilsFromUint16Buffer = "from_uint16_buffer(b)"
|
||||
PythonCommandUtilsFromInt32Buffer = "from_int32_buffer(b)"
|
||||
PythonCommandUtilsFromUint32Buffer = "from_uint32_buffer(b)"
|
||||
PythonCommandOct = "oct(x)"
|
||||
PythonCommandPhase = "phase(z)"
|
||||
PythonCommandPlot = "plot(x,y,color)"
|
||||
@@ -191,12 +335,39 @@ PythonCommandReverseWithoutArg = ".reverse()"
|
||||
PythonCommandRound = "round(x,n)"
|
||||
PythonCommandScatter = "scatter(x,y)"
|
||||
PythonCommandSeed = "seed(x)"
|
||||
PythonCommandScipyFunction = "spy.function"
|
||||
PythonCommandScipyFunctionWithoutArg = "spy.\x11"
|
||||
PythonCommandScipyLinalgFunction = "spy.linalg.function"
|
||||
PythonCommandScipyLinalgFunctionWithoutArg = "spy.linalg.\x11"
|
||||
PythonCommandScipyOptimizeFunction = "spy.optimize.function"
|
||||
PythonCommandScipyOptimizeFunctionWithoutArg = "spy.optimize.\x11"
|
||||
PythonCommandScipySignalFunction = "spy.signal.function"
|
||||
PythonCommandScipySignalFunctionWithoutArg = "spy.signal.\x11"
|
||||
PythonCommandScipySpecialFunction = "spy.special.function"
|
||||
PythonCommandScipySpecialFunctionWithoutArg = "spy.special.\x11"
|
||||
PythonCommandScipyLinalgChoSolve = "spy.linalg.cho_solve(a, b)"
|
||||
PythonCommandScipyLinalgSolveTriangular = "spy.linalg.solve_triangular(a, b)"
|
||||
PythonCommandScipyOptimizeBisect = "spy.optimize.bisect(f, a, b)"
|
||||
PythonCommandScipyOptimizeFmin = "spy.optimize.fmin(f, x0)"
|
||||
PythonCommandScipyOptimizeNewton = "spy.optimize.newton(f, x0)"
|
||||
PythonCommandScipySignalSosfilt = "spy.signal.sosfilt(sos, x)"
|
||||
PythonCommandScipySignalSpectrogram = "spy.signal.spectrogram(y)"
|
||||
PythonCommandScipySpecialErf = "spy.erf(a)"
|
||||
PythonCommandScipySpecialErfc = "spy.erfc(a)"
|
||||
PythonCommandScipySpecialGamma = "spy.gamma(a)"
|
||||
PythonCommandScipySpecialGammaln = "spy.gammaln(a)"
|
||||
PythonCommandSetPixel = "set_pixel(x,y,color)"
|
||||
PythonCommandShow = "show()"
|
||||
PythonCommandSin = "sin(x)"
|
||||
PythonCommandSinComplex = "sin(z)"
|
||||
PythonCommandSinh = "sinh(x)"
|
||||
PythonCommandSleep = "sleep(t)"
|
||||
PythonCommandLocalTime = "localtime([timestamp])"
|
||||
PythonCommandMktime = "mktime(tm)"
|
||||
PythonCommandTime = "time()"
|
||||
PythonCommandSetLocaltime = "setlocaltime(tm)"
|
||||
PythonCommandRTCmode = "rtcmode()"
|
||||
PythonCommandSetRTCmode = "setrtcmode(mode)"
|
||||
PythonCommandSort = "list.sort()"
|
||||
PythonCommandSortWithoutArg = ".sort()"
|
||||
PythonCommandSorted = "sorted(list)"
|
||||
@@ -215,15 +386,25 @@ PythonCommandUniform = "uniform(a,b)"
|
||||
PythonConstantE = "2.718281828459045"
|
||||
PythonConstantPi = "3.141592653589793"
|
||||
PythonOsCommandUname = "uname()"
|
||||
PythonOsCommandGetlogin = "getlogin()"
|
||||
PythonOsCommandRemove = "remove(filename)"
|
||||
PythonOsCommandRename = "rename(oldname, newname)"
|
||||
PythonOsCommandRemoveWithoutArg = "remove(\x11)"
|
||||
PythonOsCommandRenameWithoutArg = "rename(\x11,)"
|
||||
PythonOsCommandListdir = "listdir()"
|
||||
PythonSysCommandExit = "exit()"
|
||||
PythonSysCommandPrintexception = "print_exception(exc)"
|
||||
PythonSysCommandPrintexceptionWithoutArg = "print_exception(\x11)"
|
||||
PythonSysCommandByteorder = "byteorder"
|
||||
PythonSysCommandImplementation = "implementation"
|
||||
PythonSysCommandModules = "modules"
|
||||
PythonSysCommandVersion = "version"
|
||||
PythonSysCommandVersioninfo = "version_info"
|
||||
PythonTurtleCommandBackward = "backward(x)"
|
||||
PythonTurtleCommandCircle = "circle(r)"
|
||||
PythonTurtleCommandColor = "color('c')"
|
||||
PythonTurtleCommandColorMode = "colormode(x)"
|
||||
PythonTurtleCommandBgcolor = "bgcolor('c')"
|
||||
PythonTurtleCommandForward = "forward(x)"
|
||||
PythonTurtleCommandGoto = "goto(x,y)"
|
||||
PythonTurtleCommandHeading = "heading()"
|
||||
@@ -237,16 +418,8 @@ PythonTurtleCommandPosition = "position()"
|
||||
PythonTurtleCommandReset = "reset()"
|
||||
PythonTurtleCommandRight = "right(a)"
|
||||
PythonTurtleCommandSetheading = "setheading(a)"
|
||||
PythonTurtleCommandSetposition = "setposition(x,[y])"
|
||||
PythonTurtleCommandShowturtle = "showturtle()"
|
||||
PythonTurtleCommandSpeed = "speed(x)"
|
||||
PythonTurtleCommandWhite = "'white'"
|
||||
PythonTurtleCommandYellow = "'yellow'"
|
||||
PythonTimeModule = "time"
|
||||
PythonTimeCommandImportFrom = "from time import *"
|
||||
PythonTimeCommandSleep = "sleep()"
|
||||
PythonTimeCommandSleepDemo = "sleep(n)"
|
||||
PythonTimeCommandMonotonic = "monotonic()"
|
||||
PythonCommandFileOpen = "open(name, [mode])"
|
||||
PythonCommandFileOpenWithoutArg = "open(\x11)"
|
||||
PythonCommandFileSeek = "file.seek(offset, [whence])"
|
||||
|
||||
@@ -451,30 +451,6 @@ void ConsoleController::printText(const char * text, size_t length) {
|
||||
flushOutputAccumulationBufferToStore();
|
||||
micropython_port_vm_hook_refresh_print();
|
||||
}
|
||||
// #if __EMSCRIPTEN__
|
||||
/* If we called micropython_port_interrupt_if_needed here, we would need to
|
||||
* put in the WHITELIST all the methods that call
|
||||
* ConsoleController::printText, which means all the MicroPython methods that
|
||||
* call print... This is a lot of work + might reduce the performance as
|
||||
* emterpreted code is slower.
|
||||
*
|
||||
* We thus do not allow print interruption on the web simulator. It would be
|
||||
* better to allow it, but the biggest problem was on the device anyways
|
||||
* -> It is much quicker to interrupt Python on the web simulator than on the
|
||||
* device.
|
||||
*
|
||||
* TODO: Allow print interrpution on emscripten -> maybe by using WASM=1 ? */
|
||||
|
||||
/*
|
||||
* This can be run in Omega, since it uses WebASM.
|
||||
*/
|
||||
// #else
|
||||
/* micropython_port_vm_hook_loop is not enough to detect user interruptions,
|
||||
* because it calls micropython_port_interrupt_if_needed every 20000
|
||||
* operations, and a print operation is quite long. We thus explicitely call
|
||||
* micropython_port_interrupt_if_needed here. */
|
||||
micropython_port_interrupt_if_needed();
|
||||
// #endif
|
||||
}
|
||||
|
||||
void ConsoleController::autoImportScript(Script script, bool force) {
|
||||
|
||||
@@ -19,7 +19,7 @@ void ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::setLine(Consol
|
||||
|
||||
void ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
ctx->fillRect(bounds(), Palette::CodeBackground);
|
||||
ctx->drawString(m_line->text(), KDPointZero, GlobalPreferences::sharedGlobalPreferences()->font(), textColor(m_line), isHighlighted()? Palette::Select : Palette::BackgroundApps);
|
||||
ctx->drawString(m_line->text(), KDPointZero, GlobalPreferences::sharedGlobalPreferences()->font(), textColor(m_line), isHighlighted()? Palette::Select : Palette::CodeBackground);
|
||||
}
|
||||
|
||||
KDSize ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::minimalSizeForOptimalDisplay() const {
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "app.h"
|
||||
#include <escher/metric.h>
|
||||
#include <ion.h>
|
||||
#include "../global_preferences.h"
|
||||
#include <apps/apps_container.h>
|
||||
|
||||
using namespace Shared;
|
||||
|
||||
@@ -23,7 +25,7 @@ void EditorController::setScript(Script script, int scriptIndex) {
|
||||
m_script = script;
|
||||
m_scriptIndex = scriptIndex;
|
||||
|
||||
/* We edit the script direclty in the storage buffer. We thus put all the
|
||||
/* We edit the script directly in the storage buffer. We thus put all the
|
||||
* storage available space at the end of the current edited script and we set
|
||||
* its size.
|
||||
*
|
||||
@@ -36,8 +38,8 @@ void EditorController::setScript(Script script, int scriptIndex) {
|
||||
*
|
||||
* */
|
||||
|
||||
size_t newScriptSize = Ion::Storage::sharedStorage()->putAvailableSpaceAtEndOfRecord(m_script);
|
||||
m_editorView.setText(const_cast<char *>(m_script.content()), newScriptSize - Script::StatusSize());
|
||||
Ion::Storage::sharedStorage()->putAvailableSpaceAtEndOfRecord(m_script);
|
||||
m_editorView.setText(const_cast<char *>(m_script.content()), m_script.contentSize());
|
||||
}
|
||||
|
||||
void EditorController::willExitApp() {
|
||||
@@ -71,6 +73,10 @@ void EditorController::viewDidDisappear() {
|
||||
m_menuController->scriptContentEditionDidFinish();
|
||||
}
|
||||
|
||||
void EditorController::textAreaDidReceiveNoneXNTEvent() {
|
||||
AppsContainer::sharedAppsContainer()->resetXNT();
|
||||
}
|
||||
|
||||
bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) {
|
||||
if (App::app()->textInputDidReceiveEvent(textArea, event)) {
|
||||
return true;
|
||||
@@ -80,7 +86,6 @@ bool EditorController::textAreaDidReceiveEvent(TextArea * textArea, Ion::Events:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (event == Ion::Events::Backspace && textArea->selectionIsEmpty()) {
|
||||
/* If the cursor is on the left of the text of a line, backspace one
|
||||
* indentation space at a time. */
|
||||
|
||||
@@ -30,6 +30,7 @@ public:
|
||||
TELEMETRY_ID("Editor");
|
||||
|
||||
/* TextAreaDelegate */
|
||||
void textAreaDidReceiveNoneXNTEvent() override;
|
||||
bool textAreaDidReceiveEvent(TextArea * textArea, Ion::Events::Event event) override;
|
||||
|
||||
/* InputEventHandlerDelegate */
|
||||
|
||||
@@ -26,7 +26,9 @@ void EditorView::resetSelection() {
|
||||
}
|
||||
|
||||
void EditorView::scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) {
|
||||
m_gutterView.setOffset(scrollViewDataSource->offset().y());
|
||||
if (m_gutterView.setOffsetAndNeedResize(scrollViewDataSource->offset().y())) {
|
||||
internalLayoutSubviews(true);
|
||||
}
|
||||
}
|
||||
|
||||
View * EditorView::subviewAtIndex(int index) {
|
||||
@@ -42,8 +44,12 @@ void EditorView::didBecomeFirstResponder() {
|
||||
}
|
||||
|
||||
void EditorView::layoutSubviews(bool force) {
|
||||
m_gutterView.setOffset(0);
|
||||
KDCoordinate gutterWidth = m_gutterView.minimalSizeForOptimalDisplay().width();
|
||||
m_gutterView.setOffsetAndNeedResize(0); // Whatever the return is, we layout the editor view
|
||||
internalLayoutSubviews(force);
|
||||
}
|
||||
|
||||
void EditorView::internalLayoutSubviews(bool force) {
|
||||
KDCoordinate gutterWidth = m_gutterView.computeWidth();
|
||||
m_gutterView.setFrame(KDRect(0, 0, gutterWidth, bounds().height()), force);
|
||||
|
||||
m_textArea.setFrame(KDRect(
|
||||
@@ -67,15 +73,23 @@ void EditorView::GutterView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
KDCoordinate firstLine = m_offset / glyphSize.height();
|
||||
KDCoordinate firstLinePixelOffset = m_offset - firstLine * glyphSize.height();
|
||||
|
||||
char lineNumber[4];
|
||||
char lineNumberBuffer[m_numberOfDigits + 1];
|
||||
int numberOfLines = bounds().height() / glyphSize.height() + 1;
|
||||
for (int i=0; i<numberOfLines; i++) {
|
||||
Poincare::Integer line(i + firstLine + 1);
|
||||
line.serialize(lineNumber, 4);
|
||||
KDCoordinate leftPadding = (2 - strlen(lineNumber)) * glyphSize.width();
|
||||
int lineNumberValue = (i + firstLine + 1);
|
||||
Poincare::Integer line(lineNumberValue);
|
||||
|
||||
int lineDigits = computeNumberOfDigitsFor(lineNumberValue);
|
||||
|
||||
for (int j=0; j < m_numberOfDigits - lineDigits; j++) {
|
||||
lineNumberBuffer[j] = ' ';
|
||||
}
|
||||
|
||||
line.serialize(lineNumberBuffer + (m_numberOfDigits - lineDigits), m_numberOfDigits + 1);
|
||||
|
||||
ctx->drawString(
|
||||
lineNumber,
|
||||
KDPoint(k_margin + leftPadding, i*glyphSize.height() - firstLinePixelOffset),
|
||||
lineNumberBuffer,
|
||||
KDPoint(k_margin, i*glyphSize.height() - firstLinePixelOffset),
|
||||
m_font,
|
||||
textColor,
|
||||
backgroundColor
|
||||
@@ -83,18 +97,36 @@ void EditorView::GutterView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
}
|
||||
}
|
||||
|
||||
void EditorView::GutterView::setOffset(KDCoordinate offset) {
|
||||
bool EditorView::GutterView::setOffsetAndNeedResize(KDCoordinate offset) {
|
||||
if (m_offset == offset) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
m_offset = offset;
|
||||
|
||||
int numberOfDigits = computeMaxNumberOfDigits();
|
||||
if (numberOfDigits != m_numberOfDigits) {
|
||||
m_numberOfDigits = numberOfDigits;
|
||||
return true;
|
||||
}
|
||||
|
||||
markRectAsDirty(bounds());
|
||||
return false;
|
||||
}
|
||||
|
||||
int EditorView::GutterView::computeWidth() {
|
||||
return 2 * k_margin + (m_numberOfDigits) * m_font->glyphSize().width();
|
||||
}
|
||||
|
||||
KDSize EditorView::GutterView::minimalSizeForOptimalDisplay() const {
|
||||
int numberOfChars = 2; // TODO: Could be computed
|
||||
return KDSize(2 * k_margin + numberOfChars * Poincare::Preferences::sharedPreferences()->KDPythonFont()->glyphSize().width(), 0);
|
||||
int EditorView::GutterView::computeMaxNumberOfDigits() {
|
||||
return computeNumberOfDigitsFor((bounds().height() / m_font->glyphSize().height() + 1) + (m_offset / m_font->glyphSize().height()));
|
||||
}
|
||||
|
||||
int EditorView::GutterView::computeNumberOfDigitsFor(int value) {
|
||||
int digits = 1;
|
||||
while (value >= pow(10, digits)) {
|
||||
digits++;
|
||||
}
|
||||
return digits;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ public:
|
||||
void unloadSyntaxHighlighter() { m_textArea.unloadSyntaxHighlighter(); };
|
||||
void scrollViewDidChangeOffset(ScrollViewDataSource * scrollViewDataSource) override;
|
||||
void didBecomeFirstResponder() override;
|
||||
void internalLayoutSubviews(bool force);
|
||||
private:
|
||||
int numberOfSubviews() const override { return 2; }
|
||||
View * subviewAtIndex(int index) override;
|
||||
@@ -36,14 +37,21 @@ private:
|
||||
|
||||
class GutterView : public View {
|
||||
public:
|
||||
GutterView(const KDFont * font) : View(), m_font(font), m_offset(0) {}
|
||||
GutterView(const KDFont * font) : View(), m_font(font), m_offset(0), m_numberOfDigits(2) {}
|
||||
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
void setOffset(KDCoordinate offset);
|
||||
KDSize minimalSizeForOptimalDisplay() const override;
|
||||
bool setOffsetAndNeedResize(KDCoordinate offset); // Return true if the gutter view need to be resized
|
||||
|
||||
int computeWidth();
|
||||
int computeMaxNumberOfDigits();
|
||||
static int computeNumberOfDigitsFor(int value);
|
||||
|
||||
private:
|
||||
static constexpr KDCoordinate k_margin = 2;
|
||||
|
||||
const KDFont * m_font;
|
||||
KDCoordinate m_offset;
|
||||
int m_numberOfDigits;
|
||||
};
|
||||
|
||||
PythonTextArea m_textArea;
|
||||
|
||||
@@ -1,44 +1,17 @@
|
||||
#include "helpers.h"
|
||||
#include <string.h>
|
||||
#include <ion/unicode/code_point.h>
|
||||
#include <ion.h>
|
||||
#include <escher/clipboard.h>
|
||||
|
||||
namespace Code {
|
||||
namespace Helpers {
|
||||
|
||||
class EventTextPair {
|
||||
public:
|
||||
constexpr EventTextPair(Ion::Events::Event event, const char * text) : m_event(event), m_text(text) {}
|
||||
Ion::Events::Event event() const { return m_event; }
|
||||
const char * text() const { return m_text; }
|
||||
private:
|
||||
const Ion::Events::Event m_event;
|
||||
const char * m_text;
|
||||
};
|
||||
|
||||
static_assert('\x11' == UCodePointEmpty, "Unicode error");
|
||||
static constexpr EventTextPair sEventTextMap[] = {
|
||||
EventTextPair(Ion::Events::XNT, "x"),
|
||||
EventTextPair(Ion::Events::Exp, "exp(\x11)"),
|
||||
EventTextPair(Ion::Events::Ln, "log(\x11)"),
|
||||
EventTextPair(Ion::Events::Log, "log10(\x11)"),
|
||||
EventTextPair(Ion::Events::Imaginary, "1j"),
|
||||
EventTextPair(Ion::Events::Power, "**"),
|
||||
EventTextPair(Ion::Events::Pi, "pi"),
|
||||
EventTextPair(Ion::Events::Sqrt, "sqrt(\x11)"),
|
||||
EventTextPair(Ion::Events::Square, "**2"),
|
||||
EventTextPair(Ion::Events::Multiplication, "*"),
|
||||
EventTextPair(Ion::Events::EE, "e"),
|
||||
};
|
||||
|
||||
const char * PythonTextForEvent(Ion::Events::Event event) {
|
||||
for (size_t i=0; i<sizeof(sEventTextMap)/sizeof(sEventTextMap[0]); i++) {
|
||||
if (event == sEventTextMap[i].event()) {
|
||||
return sEventTextMap[i].text();
|
||||
for (size_t i=0; i<NumberOfPythonTextPairs; i++) {
|
||||
UTF8Helper::TextPair pair = PythonTextPairs[i];
|
||||
if (event.text() == pair.firstString()) {
|
||||
return pair.secondString();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,11 @@ bool MenuController::handleEvent(Ion::Events::Event event) {
|
||||
footer()->setSelectedButton(0);
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::ShiftBack) {
|
||||
Ion::Storage::sharedStorage()->reinsertTrash("py");
|
||||
m_selectableTableView.reloadData();
|
||||
return true;
|
||||
}
|
||||
if (event == Ion::Events::Up) {
|
||||
if (footer()->selectedButton() == 0) {
|
||||
footer()->setSelectedButton(-1);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user