Compare commits

...

1949 Commits

Author SHA1 Message Date
cb4c61fb5b spelling fix
Some checks failed
CI / general_module_workflow_php (push) Has been cancelled
2024-11-29 22:57:12 +01:00
a480f4712f added dice roll
Some checks failed
CI / general_module_workflow_php (push) Has been cancelled
2024-08-16 04:09:29 +02:00
250f64556d
Merge pull request #374 from Karaka-Management/develop
Develop
2024-04-25 01:18:25 +02:00
Dennis Eichhorn
326e2172ec fix tests 2024-04-24 23:04:50 +00:00
Dennis Eichhorn
af9a7e1f29 fix tests 2024-04-24 22:43:45 +00:00
Dennis Eichhorn
efd5580a75 fix tests 2024-04-24 21:27:04 +00:00
Dennis Eichhorn
4dff3d3289 test fixes 2024-04-24 20:59:32 +00:00
Dennis Eichhorn
126fca5574 fix tests 2024-04-24 20:34:29 +00:00
Dennis Eichhorn
5230892673 fix tests 2024-04-24 20:20:57 +00:00
Dennis Eichhorn
ca57051cd7 test fixes 2024-04-24 20:02:48 +00:00
Dennis Eichhorn
370e4fa420 update lock 2024-04-24 19:18:19 +00:00
Dennis Eichhorn
f7fe30e545 update lock 2024-04-24 19:06:59 +00:00
167c7f08e7
Merge pull request #373 from Karaka-Management/master
Back merge
2024-04-24 18:38:34 +02:00
Dennis Eichhorn
982fab8018 more tests and some fixes 2024-04-24 03:20:47 +00:00
Dennis Eichhorn
189d37580d general fixes 2024-04-19 02:08:38 +00:00
Dennis Eichhorn
121e6b4486 fix templates 2024-04-17 17:45:08 +00:00
Dennis Eichhorn
1d49ceb5a0 fix bugs 2024-04-12 00:52:09 +00:00
Dennis Eichhorn
f991f15889 autofixes 2024-04-07 17:47:07 +00:00
Dennis Eichhorn
1c2ecda287 ui fixes 2024-04-07 17:31:43 +00:00
Dennis Eichhorn
ab3e8e0939 template fixes + bug fixes + style fixes 2024-04-02 21:40:48 +00:00
Dennis Eichhorn
61f44bc044 started with template fixes 2024-03-29 15:26:01 +00:00
Dennis Eichhorn
b2cd928809 fix ICLA name 2024-03-20 08:02:39 +00:00
Dennis Eichhorn
9ca0be2825 update version requirement 2024-03-20 07:21:26 +00:00
Dennis Eichhorn
27ad14b4c5 Update master 2024-03-20 06:04:12 +00:00
Dennis Eichhorn
d6ddf6cbe9 upgrade phpunit 2024-03-20 05:16:00 +00:00
Dennis Eichhorn
a1b591d141 fix tests 2024-03-20 03:00:25 +00:00
7bb5c3eb83
Merge pull request #372 from Karaka-Management/develop
Develop
2024-03-17 23:18:31 +01:00
Dennis Eichhorn
8c2ea75430 more test fixes 2024-03-17 21:33:48 +00:00
Dennis Eichhorn
384b784995 added gif 2024-03-17 03:56:05 +00:00
Dennis Eichhorn
279bd8a3bf fix tests 2024-03-17 03:55:21 +00:00
Dennis Eichhorn
0bf99750b8 more fixes 2024-03-17 02:51:01 +00:00
Dennis Eichhorn
44098e33d2 test fixes 2024-03-17 02:36:48 +00:00
Dennis Eichhorn
5876d88901 test fixes 2024-03-16 17:56:46 +00:00
Dennis Eichhorn
7b76d797b8 code fixes 2024-03-16 14:11:43 +00:00
Dennis Eichhorn
a2e7ae6a25 Merge branch 'master' of https://github.com/Karaka-Management/phpOMS 2024-03-15 22:55:49 +00:00
Dennis Eichhorn
cc243cffd7 Merge branch 'develop' 2024-03-15 22:52:10 +00:00
Dennis Eichhorn
48c5164e12 more code fixes 2024-03-15 21:57:48 +00:00
Dennis Eichhorn
642b74ad22 code fixes 2024-03-15 20:24:39 +00:00
Dennis Eichhorn
2a41801b77 bump 2024-03-10 02:24:57 +00:00
Dennis Eichhorn
006a611a07 bump 2024-02-28 05:09:14 +00:00
381bf25f13
Merge pull request #371 from Karaka-Management/develop
Develop
2024-02-25 01:39:34 +01:00
Dennis Eichhorn
405638417e update 2024-02-25 00:38:41 +00:00
Dennis Eichhorn
e7b708185e update 2024-02-04 20:34:13 +00:00
Dennis Eichhorn
84fa78359b minor formatting fixes 2024-01-30 21:28:39 +00:00
Dennis Eichhorn
01649f0489 fix text diff bug 2024-01-30 21:01:14 +00:00
Dennis Eichhorn
84d73bf821 improve parsers 2024-01-30 21:00:59 +00:00
Dennis Eichhorn
f14f65ffd3 Fix join bugs after huge ReadMapper update 2024-01-30 21:00:44 +00:00
Dennis Eichhorn
8f735ef121 continue with db mapper optimizations 2024-01-27 10:10:43 +00:00
Dennis Eichhorn
b92e1f08e7 continue with optimizations 2024-01-27 08:40:30 +00:00
Dennis Eichhorn
67886a9dc8 bump 2024-01-27 05:43:22 +00:00
Dennis Eichhorn
4e1630a124 testing optimized ReadMapper with batched loadHasManyRelationsTest 2024-01-27 05:10:38 +00:00
Dennis Eichhorn
f1a64bdc64 auto fixes + some impl. 2024-01-26 22:54:00 +00:00
Dennis Eichhorn
560f8a2796 continue implementations 2024-01-12 00:30:21 +00:00
Dennis Eichhorn
ea0b033e1c update 2024-01-02 23:34:19 +00:00
Dennis Eichhorn
b5944503d8 bug fixes 2023-12-08 21:52:34 +00:00
Dennis Eichhorn
b447c0772c Static classes 2023-11-26 21:26:16 +00:00
Dennis Eichhorn
96f9db5395 unify epsilon definition 2023-11-11 22:39:26 +00:00
Dennis Eichhorn
047d96a776 Cleanup code 2023-11-11 22:29:00 +00:00
Dennis Eichhorn
5433e64d8e Fix code style 2023-11-11 21:44:06 +00:00
Dennis Eichhorn
d4aa5b1bc5 Update license 2023-11-11 20:43:07 +00:00
Dennis Eichhorn
f3b0ff3756 minor style fixes 2023-11-11 20:32:12 +00:00
Dennis Eichhorn
ce150dea48 Make use of str_starts_with() 2023-11-11 20:22:43 +00:00
Dennis Eichhorn
03723410dc update todo 2023-11-11 20:10:59 +00:00
Dennis Eichhorn
3bed5e3cc0 remove commented code 2023-11-11 20:06:53 +00:00
Dennis Eichhorn
bf235e34ee cleanup tag matching 2023-11-11 20:02:27 +00:00
Dennis Eichhorn
b7fa018718 Improve performance by checking for trigger char 2023-11-11 19:53:30 +00:00
Dennis Eichhorn
f3f3f2846b fox markdown bugs 2023-11-11 05:21:36 +00:00
Dennis Eichhorn
5c38b8b250 fix markdown 2023-11-10 14:46:56 +00:00
Dennis Eichhorn
0c9921b737 fix colspan attr 2023-11-10 13:58:47 +00:00
Dennis Eichhorn
6448930755 Fix em regex 2023-11-10 13:20:41 +00:00
Dennis Eichhorn
bbb9d06f29 add tests + some new markdown functionality 2023-11-10 12:28:26 +00:00
Dennis Eichhorn
36b7143829 simplify constructor 2023-11-10 04:30:02 +00:00
Dennis Eichhorn
7b90d4eb54 fix embed bug 2023-11-10 04:25:06 +00:00
Dennis Eichhorn
fa3d48bc24 add embeded audio 2023-11-10 04:22:55 +00:00
Dennis Eichhorn
171413c108 add video embeding 2023-11-10 04:12:02 +00:00
Dennis Eichhorn
268495a5f3 implement lookup table in replacement for method lookup 2023-11-10 03:56:26 +00:00
Dennis Eichhorn
d547401cb1 finish markdown cleanup 2023-11-10 03:33:21 +00:00
Dennis Eichhorn
889e71e5ab more markdown formatting fixes 2023-11-09 23:12:56 +00:00
Dennis Eichhorn
91c59ba329 fix code style 2023-11-09 22:43:57 +00:00
Dennis Eichhorn
d904e6e0bc autofixes 2023-11-09 20:04:44 +00:00
Dennis Eichhorn
4645d59b8a started with markdown formatting 2023-11-09 00:25:34 +00:00
Dennis Eichhorn
9018cf5b57 update 2023-11-09 00:18:12 +00:00
Dennis Eichhorn
1675a82410 fix minor bugs 2023-11-02 23:55:19 +00:00
Dennis Eichhorn
dd0a71421a Fix rest request bugs 2023-11-02 23:54:49 +00:00
Dennis Eichhorn
d22f0a6d18 fix tests 2023-10-24 20:46:00 +00:00
Dennis Eichhorn
ec49bf2dc1 fix tests 2023-10-24 18:39:14 +00:00
Dennis Eichhorn
999ec823b3 fix tests 2023-10-24 14:48:58 +00:00
Dennis Eichhorn
d96a842e81 fix circular dependencies 2023-10-24 00:53:11 +00:00
Dennis Eichhorn
61253e92b4 fix tests 2023-10-24 00:27:38 +00:00
Dennis Eichhorn
b871ba283c fix tests 2023-10-23 23:26:59 +00:00
Dennis Eichhorn
1b738dfe5a fix tests 2023-10-23 23:10:36 +00:00
Dennis Eichhorn
45bab0c041 fix dot to mult 2023-10-23 22:31:20 +00:00
Dennis Eichhorn
5f8004da25 adjust dot product 2023-10-23 22:29:46 +00:00
Dennis Eichhorn
b7c9453621 fix chartjs test 2023-10-23 20:26:37 +00:00
Dennis Eichhorn
479c48b713 test fixes 2023-10-23 18:58:37 +00:00
Dennis Eichhorn
f79ba2f67e test fixes 2023-10-23 18:34:59 +00:00
Dennis Eichhorn
d2d0c6bfcf fix tests 2023-10-23 18:06:30 +00:00
Dennis Eichhorn
bf9d528076 fix tests 2023-10-23 16:30:58 +00:00
Dennis Eichhorn
ab7b467c1d fixing tests 2023-10-23 02:15:22 +00:00
Dennis Eichhorn
660e2dbbfd bump 2023-10-23 01:49:26 +00:00
Dennis Eichhorn
8c5486bed4 type check 2023-10-23 01:10:53 +00:00
Dennis Eichhorn
60fa60a91a fix type 2023-10-23 00:53:55 +00:00
Dennis Eichhorn
310a716769 bump 2023-10-23 00:29:28 +00:00
Dennis Eichhorn
ab5230b8bd bump 2023-10-23 00:02:39 +00:00
Dennis Eichhorn
58120ac97d reduce slow running test 2023-10-22 23:38:40 +00:00
Dennis Eichhorn
b4384f965a bump 2023-10-22 23:17:39 +00:00
Dennis Eichhorn
484963099d bump 2023-10-22 22:52:51 +00:00
Dennis Eichhorn
31a77c08e5 fix tests 2023-10-22 22:25:59 +00:00
Dennis Eichhorn
bbbf96ad8e fix ical parser 2023-10-22 22:01:55 +00:00
Dennis Eichhorn
6e461461e0 test fixes 2023-10-22 21:28:57 +00:00
Dennis Eichhorn
5ba31111bc fix tests 2023-10-22 21:12:02 +00:00
Dennis Eichhorn
95eb37853e fix tests 2023-10-22 20:55:05 +00:00
Dennis Eichhorn
cd36282b4f fix tests 2023-10-22 20:35:57 +00:00
Dennis Eichhorn
17603e2d05 fix tests 2023-10-22 20:20:35 +00:00
Dennis Eichhorn
941bdac44e test fixes 2023-10-22 20:05:14 +00:00
Dennis Eichhorn
d8e0d40c6a fix tests 2023-10-22 19:20:45 +00:00
Dennis Eichhorn
630a38b897 fix tests 2023-10-22 19:00:42 +00:00
Dennis Eichhorn
4bed0db195 fix tests 2023-10-22 18:39:32 +00:00
Dennis Eichhorn
1e197375c5 fix tests 2023-10-22 18:26:48 +00:00
Dennis Eichhorn
f435905146 test fixes 2023-10-22 18:06:50 +00:00
Dennis Eichhorn
90b807093b fix tests 2023-10-22 17:51:18 +00:00
Dennis Eichhorn
1f9f97f8d9 fix matrix exp and cosine metric 2023-10-22 17:19:44 +00:00
Dennis Eichhorn
c52b6c8863 fix parameter order 2023-10-22 16:54:39 +00:00
Dennis Eichhorn
8f0f105b8a fix type division instead of multiplication 2023-10-22 16:30:04 +00:00
Dennis Eichhorn
3656d6df97 fix tests 2023-10-22 16:08:16 +00:00
Dennis Eichhorn
8c9e6929d0 fix tests 2023-10-22 15:35:17 +00:00
Dennis Eichhorn
8b3daf3c8d fix tests 2023-10-22 15:21:12 +00:00
Dennis Eichhorn
7a086fea93 fix tests 2023-10-22 14:33:57 +00:00
Dennis Eichhorn
2cbbe69bac test fixes 2023-10-22 14:15:33 +00:00
Dennis Eichhorn
a4f7d2e527 test fixes 2023-10-22 13:55:10 +00:00
Dennis Eichhorn
5a1ea1ee49 fix tests 2023-10-22 13:22:00 +00:00
Dennis Eichhorn
fdcf1645f2 fix tests 2023-10-22 13:05:04 +00:00
Dennis Eichhorn
8fd2cca24b fix sum type 2023-10-22 12:46:49 +00:00
Dennis Eichhorn
9c02749567 test fixes 2023-10-22 12:27:59 +00:00
Dennis Eichhorn
772453e753 fix compress type 2023-10-22 12:08:25 +00:00
Dennis Eichhorn
8a8ee4ed90 fix tests 2023-10-22 11:52:44 +00:00
Dennis Eichhorn
60ccfdb242 fix tests 2023-10-22 10:09:40 +00:00
Dennis Eichhorn
9d2b2e2e06 test fixes 2023-10-22 09:37:22 +00:00
Dennis Eichhorn
65264e33ae fix test 2023-10-22 09:00:41 +00:00
Dennis Eichhorn
c224209c28 fix tests 2023-10-22 04:32:50 +00:00
Dennis Eichhorn
9b71428f88 fix tests 2023-10-22 04:03:56 +00:00
Dennis Eichhorn
b4af5e237c fix datamapper 2023-10-22 03:40:58 +00:00
Dennis Eichhorn
5e6ccb0b36 test some broken tests 2023-10-22 03:37:37 +00:00
Dennis Eichhorn
663cf6b11e impl. more tests 2023-10-22 02:59:46 +00:00
Dennis Eichhorn
4a208b8cd0 change icon font to google icons 2023-10-19 21:44:09 +00:00
Dennis Eichhorn
0d8a2fc59d update readme 2023-10-19 17:54:59 +00:00
Dennis Eichhorn
9c86108a0f revert api function changes 2023-10-18 12:30:42 +00:00
Dennis Eichhorn
dcc60246df fix null checks 2023-10-15 19:58:55 +00:00
Dennis Eichhorn
2b6e7b008d null fixes 2023-10-15 19:32:04 +00:00
Dennis Eichhorn
bd29e83c06 remove DataMapperFactory line 697 2023-10-15 19:12:07 +00:00
Dennis Eichhorn
4807dcf5c2 fix tests 2023-10-15 18:58:36 +00:00
Dennis Eichhorn
e997408bb6 null checks 2023-10-15 18:14:27 +00:00
Dennis Eichhorn
0b5d51f9b8 code fixes 2023-10-15 17:41:45 +00:00
Dennis Eichhorn
b9aec88a4b Merge branch 'develop' 2023-10-15 16:35:34 +00:00
Dennis Eichhorn
513fa7bf8b test fixes 2023-10-15 13:43:45 +00:00
Dennis Eichhorn
ae6391ecf8 fix tests 2023-10-15 13:17:02 +00:00
Dennis Eichhorn
624d6b517e code analysis fixes 2023-10-15 12:45:18 +00:00
Dennis Eichhorn
2655c816a9 fix model visibilities 2023-10-15 11:53:12 +00:00
Dennis Eichhorn
567ab3bfcd todos fixed 2023-10-12 22:49:21 +00:00
Dennis Eichhorn
99211861eb update 2023-10-09 22:06:39 +00:00
Dennis Eichhorn
eff9f243d9 fixes #299 2023-10-05 11:58:36 +00:00
Dennis Eichhorn
007fc6dfe8 fix status code 2023-10-05 10:13:08 +00:00
Dennis Eichhorn
cd9a5cdc11 fix bug and add query yield 2023-10-05 10:12:56 +00:00
Dennis Eichhorn
e873f909fd add exists functionality (similar to count but just checks existence) 2023-10-04 23:57:30 +00:00
Dennis Eichhorn
febcc20001 improve grammar performance 2023-10-04 23:57:10 +00:00
2e32c8a7cc
Merge pull request #330 from Karaka-Management/develop
Merge
2023-10-04 17:30:06 +02:00
Dennis Eichhorn
6dcb540248 Merge branch 'feature-mapper-reflectionless' into develop 2023-10-04 15:28:14 +00:00
a3f4d61b6e
Merge pull request #329 from Karaka-Management/feature-mapper-reflectionless
Feature mapper reflectionless
2023-10-04 17:27:13 +02:00
Dennis Eichhorn
d42fee56af fix datetime value bug 2023-10-04 15:13:20 +00:00
Dennis Eichhorn
39418dbe23 phpcs fixes 2023-10-04 13:54:38 +00:00
Dennis Eichhorn
e51b7ba93c expand impression with end time 2023-10-04 01:51:51 +00:00
Dennis Eichhorn
cdea41f714 Reduce reflection usage by forcing private definition in mappers. 2023-10-03 02:19:22 +00:00
Dennis Eichhorn
be8ae797db fix phpunit config 2023-10-02 04:13:30 +00:00
Dennis Eichhorn
42ca4d6690 fix autoloading 2023-10-02 02:56:47 +00:00
Dennis Eichhorn
69f64f331b fix mssql login/password 2023-10-01 20:47:08 +00:00
Dennis Eichhorn
bdf238a522 fix link 2023-10-01 20:41:42 +00:00
Dennis Eichhorn
7505eadee1 string check 2023-10-01 16:40:10 +00:00
Dennis Eichhorn
39a55a590b fix vendor autoload loading 2023-10-01 15:52:46 +00:00
Dennis Eichhorn
48de45149b change db credentials 2023-10-01 03:14:35 +00:00
Dennis Eichhorn
3d8d0abaf6 add coverage upload 2023-09-30 17:40:10 +00:00
695984e4fe
Merge pull request #328 from Karaka-Management/develop
Merge pull request #327 from Karaka-Management/master
2023-09-30 18:50:06 +02:00
9699842a7e
Merge pull request #327 from Karaka-Management/master
handle delete exception
2023-09-30 15:14:07 +02:00
Dennis Eichhorn
d56488a58a handle delete exception 2023-09-30 02:34:21 +00:00
Dennis Eichhorn
83277e9b6f fix autoloading 2023-09-29 20:24:37 +00:00
Dennis Eichhorn
8efe04fc6b unused far fix 2023-09-29 16:43:18 +00:00
Dennis Eichhorn
135f141c06 fix composer file 2023-09-29 04:32:27 +00:00
Dennis Eichhorn
d9167a9d06 fix tests 2023-09-29 04:09:40 +00:00
Dennis Eichhorn
fa68acc4be fix tests 2023-09-29 03:01:06 +00:00
Dennis Eichhorn
13bf197ac7 replace stripos with str_starts_with 2023-09-29 02:22:20 +00:00
Dennis Eichhorn
5d66591a55 improve autoloading performance with class map 2023-09-29 02:21:34 +00:00
Dennis Eichhorn
b969bc927c impl. permission check 2023-09-28 21:49:15 +00:00
Dennis Eichhorn
abff265761 minor test fixes 2023-09-28 15:34:43 +00:00
Dennis Eichhorn
be8e1c8526 fix autoloader 2023-09-28 02:53:02 +00:00
Dennis Eichhorn
b51dfbd9ca fix tests 2023-09-28 01:04:16 +00:00
Dennis Eichhorn
ac5273bbc5 add multi_autoincrement to db column 2023-09-27 20:25:28 +00:00
Dennis Eichhorn
d272df38d4 fix sql connection tests 2023-09-27 18:56:46 +00:00
Dennis Eichhorn
ccca21c0e3 fix tests 2023-09-27 18:31:16 +00:00
Dennis Eichhorn
e07798e3b6 fix update query 2023-09-27 18:16:48 +00:00
Dennis Eichhorn
ee9391fd97 fix includes 2023-09-27 17:56:20 +00:00
Dennis Eichhorn
f445678207 fix tests 2023-09-27 17:32:55 +00:00
Dennis Eichhorn
1ca15ebbfa fix tests 2023-09-27 16:55:10 +00:00
Dennis Eichhorn
513a1df1dc fix tests 2023-09-27 14:42:42 +00:00
Dennis Eichhorn
4327536119 fix tests 2023-09-27 13:13:08 +00:00
Dennis Eichhorn
9cef4cddaf fix autoloading 2023-09-27 04:25:24 +00:00
Dennis Eichhorn
fb35f86c5c fix tests 2023-09-27 03:35:04 +00:00
Dennis Eichhorn
fe9f2f3954 alternative autoloader test 2023-09-27 03:29:41 +00:00
Dennis Eichhorn
3200e2abed test fix 2023-09-27 03:22:02 +00:00
Dennis Eichhorn
5f551fe5f3 fix tests 2023-09-27 02:56:50 +00:00
Dennis Eichhorn
f498435a41 fix false return 2023-09-27 02:03:01 +00:00
Dennis Eichhorn
6c84a1e6af fix tests 2023-09-27 01:22:16 +00:00
Dennis Eichhorn
250edfdb63 fix framework 2023-09-27 01:15:50 +00:00
Dennis Eichhorn
40acf30ad9 fix tests 2023-09-27 00:47:48 +00:00
Formatter Bot
913f044dc2 Automated formatting changes (NO_CI) 2023-09-26 23:12:02 +00:00
Dennis Eichhorn
a0de10c939 add CsvDatabaseMapper 2023-09-26 23:07:51 +00:00
Dennis Eichhorn
2cbab79465 simplify inspection 2023-09-26 22:12:26 +00:00
Dennis Eichhorn
213ed899a9 lighthouse improvements 2023-09-26 20:49:44 +00:00
Dennis Eichhorn
6e25ad9313 fix header render 2023-09-26 18:51:27 +00:00
Dennis Eichhorn
8cec0e3dfe fix header render 2023-09-26 18:26:28 +00:00
Dennis Eichhorn
33cf7b521e fix header render 2023-09-26 18:25:18 +00:00
Dennis Eichhorn
6840f9b9e7 fix tests 2023-09-25 22:54:40 +00:00
Dennis Eichhorn
2dbaeba97e fix tests 2023-09-25 21:55:20 +00:00
Dennis Eichhorn
3f3ec8b697 fix tests 2023-09-25 19:59:42 +00:00
Dennis Eichhorn
9b1104037f fix tests 2023-09-25 17:28:10 +00:00
Dennis Eichhorn
397696c122 fix tests 2023-09-25 14:27:20 +00:00
Dennis Eichhorn
ea2ba6aa7d test fixes 2023-09-24 20:29:23 +00:00
Dennis Eichhorn
4611258418 fix test script 2023-09-24 18:23:45 +00:00
Dennis Eichhorn
f11873cb4c fix tests 2023-09-24 17:57:28 +00:00
Dennis Eichhorn
72ec944756 fix vendor 2023-09-24 16:03:39 +00:00
Dennis Eichhorn
3fa5184167 fix tests 2023-09-24 14:19:21 +00:00
Dennis Eichhorn
23cf5e4a48 Merge branch 'develop' of https://github.com/Karaka-Management/phpOMS into develop 2023-09-24 04:01:17 +00:00
Dennis Eichhorn
28a6ec5951 fix db handling 2023-09-24 03:57:33 +00:00
Formatter Bot
80131384cb Automated formatting changes 2023-09-24 03:54:43 +00:00
Dennis Eichhorn
f83e60a592 test fixes 2023-09-24 03:50:15 +00:00
Dennis Eichhorn
5de349ba68 fix tests 2023-09-24 02:17:50 +00:00
Dennis Eichhorn
377dc8a821 fix tests 2023-09-24 00:45:57 +00:00
Dennis Eichhorn
788755dd60 test fixes 2023-09-24 00:08:27 +00:00
Dennis Eichhorn
f45fb503fb merge 2023-09-23 15:53:27 +00:00
Dennis Eichhorn
c10e65bcf5 test fixes 2023-09-23 15:51:59 +00:00
Formatter Bot
e7ceebfccb Automated formatting changes 2023-09-23 13:46:33 +00:00
Dennis Eichhorn
85bed9ec2f fix tests 2023-09-23 13:41:56 +00:00
Dennis Eichhorn
75dc3bc7d3 fix tests 2023-09-23 11:34:46 +00:00
Dennis Eichhorn
3264ca7ccb fix tests 2023-09-23 01:36:54 +00:00
Dennis Eichhorn
6c0651afa6 trying to fix iCCP bug 2023-09-23 00:53:40 +00:00
Dennis Eichhorn
9e2efeff7d trying to fix iCCP bug 2023-09-23 00:51:32 +00:00
Dennis Eichhorn
ac3c43e17d fixes 2023-09-23 00:35:43 +00:00
Dennis Eichhorn
c224fe74d5 fix tests 2023-09-22 23:25:21 +00:00
Dennis Eichhorn
94b293e1df bug fix 2023-09-22 17:56:11 +00:00
Dennis Eichhorn
ddd1b04b3a fix tests 2023-09-22 02:18:05 +00:00
Formatter Bot
aecb807555 Automated formatting changes 2023-09-22 01:45:43 +00:00
Dennis Eichhorn
650789ba16 fix tests 2023-09-22 01:42:19 +00:00
Dennis Eichhorn
662651236e Fix tests 2023-09-22 00:07:11 +00:00
Dennis Eichhorn
9c1c339d37 merge 2023-09-21 23:37:49 +00:00
Dennis Eichhorn
82a14e4704 test fixes 2023-09-21 23:37:23 +00:00
Formatter Bot
7fea04d08e Automated formatting changes 2023-09-21 23:30:31 +00:00
Dennis Eichhorn
455c9c8069 merge 2023-09-21 23:26:27 +00:00
Dennis Eichhorn
c87d1df047 merge 2023-09-21 23:25:45 +00:00
Dennis Eichhorn
5c9b0e88c3 fix tests 2023-09-21 23:25:21 +00:00
Dennis Eichhorn
b6b9dd39b9 add references/licenses 2023-09-21 22:52:21 +00:00
Formatter Bot
0080e35aac Automated formatting changes 2023-09-21 22:50:19 +00:00
Dennis Eichhorn
dfd81edcc3 minor improvements 2023-09-21 22:46:35 +00:00
Dennis Eichhorn
58de0b90df autofix 2023-09-21 22:28:18 +00:00
Dennis Eichhorn
118789e0f8 add url parsing 2023-09-21 22:26:45 +00:00
Dennis Eichhorn
acf4ea21f3 test fixes 2023-09-21 22:22:41 +00:00
Dennis Eichhorn
05d913b09a update markdown 2023-09-21 22:22:25 +00:00
Dennis Eichhorn
b69c9b708c update markdown 2023-09-21 22:22:09 +00:00
Dennis Eichhorn
37db31e85f test fixes 2023-09-21 19:32:09 +00:00
Dennis Eichhorn
5d2ff0aa47 fix tests 2023-09-21 18:56:22 +00:00
Dennis Eichhorn
0dec47823e fix tests 2023-09-21 18:55:20 +00:00
Formatter Bot
ef3849164a Automated formatting changes 2023-09-21 18:35:34 +00:00
Dennis Eichhorn
c2dea0f000 fix tests 2023-09-21 18:32:09 +00:00
Dennis Eichhorn
e8fbb0bc2c fix tests 2023-09-21 16:59:06 +00:00
Dennis Eichhorn
173c501b54 Merge branch 'develop' of https://github.com/Karaka-Management/phpOMS into develop 2023-09-21 16:55:17 +00:00
Dennis Eichhorn
4f48347c16 code fixes 2023-09-21 16:55:15 +00:00
Formatter Bot
06471f5f71 Automated formatting changes 2023-09-21 16:42:46 +00:00
Dennis Eichhorn
cf72e2f5ec fix tests 2023-09-21 16:37:19 +00:00
Dennis Eichhorn
6e0aebb074 fix tests 2023-09-21 16:15:09 +00:00
Dennis Eichhorn
ad982dda8f fix deprecated functions 2023-09-21 16:09:25 +00:00
Dennis Eichhorn
eddc7bff03 fix tests 2023-09-21 15:54:06 +00:00
Dennis Eichhorn
7882ce95be fix test 2023-09-21 15:32:28 +00:00
Dennis Eichhorn
d78dfa7e74 fix tests 2023-09-21 15:20:42 +00:00
Dennis Eichhorn
2473992319 fix tests 2023-09-21 15:02:16 +00:00
Dennis Eichhorn
6be8c1fdc4 fix test bugs 2023-09-21 14:51:29 +00:00
Dennis Eichhorn
d5b0b73f2a fix tests 2023-09-21 14:44:14 +00:00
Dennis Eichhorn
cd00e471b9 fix tests 2023-09-21 14:11:14 +00:00
Dennis Eichhorn
c88829efd6 fix tests 2023-09-21 13:29:17 +00:00
Dennis Eichhorn
1e23943085 fix tests 2023-09-21 13:19:11 +00:00
Dennis Eichhorn
64aec26f95 fix class abstract 2023-09-21 13:12:10 +00:00
Dennis Eichhorn
ff53814f43 fix config 2023-09-21 13:10:15 +00:00
Dennis Eichhorn
829bef8f01 fix test bugs 2023-09-21 13:00:54 +00:00
Dennis Eichhorn
0c612c339d fix tests 2023-09-21 12:51:20 +00:00
Dennis Eichhorn
6805b24820 code fixes 2023-09-21 12:41:42 +00:00
Dennis Eichhorn
d1edf04232 code fixes 2023-09-21 12:32:00 +00:00
Dennis Eichhorn
6b74b8d968 code fixes 2023-09-21 12:06:14 +00:00
Dennis Eichhorn
0d200da299 fix bugs 2023-09-21 11:35:17 +00:00
Dennis Eichhorn
e579f1ab30 type hint fix 2023-09-21 03:39:53 +00:00
40b794d880
Update main.yml 2023-09-21 05:35:47 +02:00
Dennis Eichhorn
9793782e48 update composer versions 2023-09-21 03:31:05 +00:00
Dennis Eichhorn
b9bd5d618f Merge branch 'develop' of https://github.com/Karaka-Management/phpOMS into develop 2023-09-21 03:21:59 +00:00
dea660ca91
Update main.yml 2023-09-21 05:18:02 +02:00
Dennis Eichhorn
0b9a8687e6 fix cpu usage bugs 2023-09-21 03:13:48 +00:00
Dennis Eichhorn
9078fe6f65 fix cpu usage bugs 2023-09-21 03:12:33 +00:00
Dennis Eichhorn
5b52a92d38 fix cpu usage bugs 2023-09-21 03:12:12 +00:00
Dennis Eichhorn
3925cb6be7 inspection fixes 2023-09-21 03:11:01 +00:00
Dennis Eichhorn
d8fd9b74d2 add path value retrieval 2023-09-21 02:37:39 +00:00
Dennis Eichhorn
17756362a1 cs fixes 2023-09-21 02:24:44 +00:00
Dennis Eichhorn
5babc18595 fix rector run 2023-09-21 02:10:17 +00:00
Dennis Eichhorn
af38754915 automated rector fixes 2023-09-21 02:02:27 +00:00
Dennis Eichhorn
7bf216708b automated fixes 2023-09-21 01:43:12 +00:00
Dennis Eichhorn
c9a03bfff3 automated fixes 2023-09-21 01:41:56 +00:00
Dennis Eichhorn
177d7cf2b5 update composer 2023-09-21 01:21:10 +00:00
Dennis Eichhorn
9f319c4e30 update composer 2023-09-21 01:16:23 +00:00
Dennis Eichhorn
9a99bea741 update composer 2023-09-21 01:10:55 +00:00
Dennis Eichhorn
f5887798c2 Add tests for rating and fix bugs 2023-09-20 23:05:30 +00:00
Dennis Eichhorn
9843328a14 make getDataJson return array also for single values 2023-09-19 17:13:05 +00:00
Dennis Eichhorn
11d2ed8f2e add header timestamp 2023-09-19 03:52:20 +00:00
Dennis Eichhorn
0844846f51 improve request stats 2023-09-18 23:30:21 +00:00
Dennis Eichhorn
61eb86ae6f update stats 2023-09-17 17:07:23 +00:00
Dennis Eichhorn
2f0e9d1c8c remove var_dump 2023-09-17 12:34:36 +00:00
Dennis Eichhorn
3493ac10b1 impl. request stat collection 2023-09-17 01:44:15 +00:00
Dennis Eichhorn
4e4405ade1 fig getAll queries 2023-09-16 22:20:18 +00:00
Dennis Eichhorn
84cf2e96ce attempty to fix empty mapper requests 2023-09-14 12:46:59 +00:00
Dennis Eichhorn
e08f689afc manual status added 2023-09-11 21:59:31 +00:00
Dennis Eichhorn
018b9ce981 update 2023-09-10 18:58:35 +00:00
Dennis Eichhorn
4469789af4 auto fixes 2023-08-30 11:53:16 +00:00
Dennis Eichhorn
447efca623 format fixes 2023-08-30 11:44:08 +00:00
Dennis Eichhorn
74e1684ad0 update 2023-08-28 22:06:37 +00:00
Dennis Eichhorn
c4fc99ed39 add data/content type handling 2023-08-14 16:40:30 +00:00
Dennis Eichhorn
61c9bacb80 fix cdf function + add icdf 2023-08-14 16:39:53 +00:00
Dennis Eichhorn
ab023cad8b replace \Closure with Callable 2023-08-14 16:39:07 +00:00
Dennis Eichhorn
11b6f5f471 replace \Closure with Callable 2023-08-14 16:38:39 +00:00
Dennis Eichhorn
bc1cd635fe Fix erf and erfc function + impl erfcinv 2023-08-14 16:37:19 +00:00
Dennis Eichhorn
1a7fe13e66 Equation solvers 2023-08-14 16:36:28 +00:00
Dennis Eichhorn
d36e96cb85 fixed various exception docblocks 2023-08-06 20:17:43 +00:00
Dennis Eichhorn
e91e5fd405 fix default respone generation 2023-07-26 09:18:05 +00:00
Dennis Eichhorn
83a36c1c66 added api functions 2023-07-24 06:01:32 +00:00
Dennis Eichhorn
513df8987b continue impl 2023-07-23 03:00:15 +00:00
Dennis Eichhorn
27ac3f18a6 update 2023-07-17 01:39:34 +00:00
Dennis Eichhorn
ebbc08fe9b backup 2023-07-09 02:32:02 +00:00
Dennis Eichhorn
acf9a247f0 Improve many-to-many query performance 2023-06-18 13:02:13 +00:00
Dennis Eichhorn
0fd9b3edd7 reduce has many query complexity 2023-06-18 02:44:18 +00:00
Dennis Eichhorn
c9c41a7212 expand permission handling 2023-06-18 02:44:00 +00:00
f802139f33 Fix file header 2023-06-17 03:13:39 +02:00
71389a6796 Expand depreciation. 2023-06-15 01:50:16 +02:00
Dennis Eichhorn
1da071f202 Quick backup before crash 2023-06-13 18:55:52 +00:00
Dennis Eichhorn
f1a2c81aeb continue implementation 2023-06-09 17:39:31 +00:00
ebc270c84e Simplify getData() 2023-06-09 19:33:47 +02:00
Dennis Eichhorn
f88a530b96 automated phpcs fixes 2023-05-31 13:21:48 +00:00
Dennis Eichhorn
c2538fed60 fix github script 2023-05-30 14:02:35 +00:00
Dennis Eichhorn
04cb75cede Merge branch 'develop' of https://github.com/Karaka-Management/phpOMS into develop 2023-05-30 13:59:29 +00:00
318028da28 Continue with getter/setter cleanup 2023-05-30 15:44:27 +02:00
e05dbd4156 continue with getter/setter removal 2023-05-30 04:15:43 +02:00
678f066a41 use direct data access for response data 2023-05-30 03:42:53 +02:00
06f1784418 Allow l11n type to reference the l11n. 2023-05-30 01:34:01 +02:00
Dennis Eichhorn
1dd478c461 expand composer 2023-05-28 13:51:32 +00:00
Dennis Eichhorn
0900e31d45 phcbf autofixes 2023-05-28 12:38:27 +00:00
Dennis Eichhorn
a4be7fd316 phpcs autofixes 2023-05-28 12:19:04 +00:00
Dennis Eichhorn
055d25425e phpcs auto fixes 2023-05-28 04:00:43 +00:00
Dennis Eichhorn
3938f56f88 cs fixes 2023-05-28 03:56:49 +00:00
Dennis Eichhorn
f09df7ea16 rector fixes + bug fixes 2023-05-27 03:06:46 +00:00
Dennis Eichhorn
fc2fd1343f Improve performance 2023-05-25 12:19:24 +00:00
Dennis Eichhorn
feb054b8fb Fix encryption tests 2023-05-24 18:05:56 +00:00
Dennis Eichhorn
b3663ac127 Fix enum/location 2023-05-24 18:05:49 +00:00
Dennis Eichhorn
3e3be15c13 Add depreciation types 2023-05-24 18:05:33 +00:00
Dennis Eichhorn
dfb57a37df Add geocoding api 2023-05-24 18:05:14 +00:00
Dennis Eichhorn
88f2b7a585 Add default json responses 2023-05-24 18:05:00 +00:00
Dennis Eichhorn
55c267f01f Allow to set data array 2023-05-24 18:04:51 +00:00
Dennis Eichhorn
96ac1d9dff fix ftp port and code content 2023-05-19 14:45:32 +00:00
Dennis Eichhorn
4d9f4aa241 test fixes + new test data 2023-05-19 02:37:35 +00:00
Dennis Eichhorn
475b52e67c fixes 2023-05-09 16:07:44 +00:00
Dennis Eichhorn
fafa6cd3cd remove todo 2023-05-07 20:38:07 +00:00
Dennis Eichhorn
a9f04acb31 add creditsafe api 2023-05-06 23:16:59 +00:00
Dennis Eichhorn
1bd56c74ac fix enum type 2023-05-06 11:47:26 +00:00
Dennis Eichhorn
9edbe6cc4b make id public, organigram impl. media password/encryption, settings bug fix, Money->FloatInt change, ... 2023-05-06 11:42:06 +00:00
Dennis Eichhorn
c81bae26cf unset SERVER to prevent leaks 2023-05-06 11:38:01 +00:00
Dennis Eichhorn
3457f16cd7 added vat validation 2023-05-06 11:37:08 +00:00
Dennis Eichhorn
7c01ac51e9 bug fixes and subscription improvements 2023-04-25 01:51:28 +00:00
Dennis Eichhorn
c47d3bb6c1 prepare workflows 2023-04-21 19:13:03 +00:00
004eb33a4f test fixes 2023-04-17 19:44:57 +02:00
5b2c9d499b fix demoSetup 2023-04-16 01:55:36 +02:00
3d68874c2c fix static analysis 2023-04-11 00:20:13 +02:00
859a04c791 fix static analysis 2023-04-09 06:03:39 +02:00
b9cc466bed fix billing process 2023-04-08 04:36:26 +02:00
4d0a6e5c2d fix login bugs 2023-03-31 00:25:51 +02:00
Dennis Eichhorn
f9ae1c3c85 add status codes and status code rendering 2023-03-26 22:50:02 +00:00
Dennis Eichhorn
ec210f8b8e add custom tags 2023-03-25 22:23:22 +00:00
a9745c2f1c registration fixes 2023-03-24 16:20:25 +01:00
a7493d205b too many changes 2023-03-11 23:38:20 +01:00
bbbeee84e1 many small fixes 2023-02-10 18:20:57 +01:00
df4611731f phpstan, phpcs, phpunit fixes 2023-01-27 22:12:09 +01:00
9cb5138201 change from org to unit 2023-01-26 21:42:31 +01:00
0bfb0c2fe1 change from org to unit 2023-01-26 21:42:24 +01:00
de4f390344 change from org to unit 2023-01-26 21:42:06 +01:00
65b455f6c0 change org to unit 2023-01-26 21:41:44 +01:00
ce8b9988bf change to cli 2023-01-26 21:40:43 +01:00
8bace3becf improve doclblock + remove unused var 2023-01-26 21:40:30 +01:00
6e42fe49a1 edit docblock + add factory support 2023-01-26 21:39:53 +01:00
778a8f02eb change docblock 2023-01-26 21:39:23 +01:00
44dc418ca3 add unit 2023-01-26 21:39:07 +01:00
bf48a9b1bf rename org to unit 2023-01-26 21:38:08 +01:00
c9e6d6a210 add unit/app 2023-01-26 21:37:26 +01:00
5902fbdf08 change console to cli 2023-01-26 21:36:58 +01:00
de1bf517c2 autoloader loading guard, cache flush fix, transactions, ALT datamapper loading, table linter fix, session handling for caches, file path guard, image diff, directory delete guard, general localization model, office parsers 2023-01-07 18:55:22 +01:00
1bc05c79d6 remove unused variable 2022-12-28 03:49:21 +01:00
de6831cf36 fix phpstan lvl 9 bugs 2022-12-26 20:52:58 +01:00
6e52397ab4 test fixes 2022-12-26 16:10:12 +01:00
4a3410d182 fix perm 2022-12-26 13:35:10 +01:00
3740f24c39 fix tests after changing to interface 2022-12-24 23:58:45 +01:00
7889f9ad7c fix some ftp bugs 2022-12-24 23:58:30 +01:00
0cf775c8dd add app config 2022-12-24 23:58:18 +01:00
092c9b9f29 be more defensive about array index 2022-12-24 23:58:00 +01:00
88938b7fd1 add resize function incl. docblock 2022-12-24 23:57:26 +01:00
3d26dc8fdd add uuid 2022-12-24 23:57:11 +01:00
a27b433ef4 use router interface more strictly 2022-12-24 23:56:56 +01:00
8d4736256f fix language name length 2022-12-24 23:56:25 +01:00
c35eb52a8b add id 2022-12-24 23:56:10 +01:00
321425ea1f fix type hints 2022-12-24 23:55:40 +01:00
476fc943e9 handle correlation quantity 2022-12-24 23:55:26 +01:00
af4dca3ee4 start adding payment api wrapper 2022-12-24 23:55:07 +01:00
a125925f29 Fix path bug 2022-12-22 12:30:47 +01:00
833886f970 add function to retreive Currency 2022-12-22 12:30:02 +01:00
cd0456e1be Start adding Api wrappers 2022-12-22 12:29:35 +01:00
d07c15d1e4 add uuid function 2022-12-22 12:28:56 +01:00
e24f460fdf fix url 2022-12-16 21:59:21 +01:00
5844ad3a72 update config 2022-12-16 19:27:48 +01:00
60810e17a9 fix indent 2022-12-16 19:07:06 +01:00
01be5c32d2 update mssql setup? 2022-12-16 18:57:04 +01:00
51779fb92b fix interface 2022-12-10 23:53:36 +01:00
3fdc684973 fix dependencies 2022-12-10 23:19:18 +01:00
82cdc54fb0 fix linting 2022-12-10 22:58:04 +01:00
7d9a033833 fix url 2022-12-10 22:16:04 +01:00
190d5cac11 fix tests 2022-11-25 23:50:30 +01:00
868ad1d5c4 change to strict comparison 2022-11-25 23:49:56 +01:00
8c3d4fffa5 fix tests 2022-11-25 21:50:07 +01:00
df7bbbdb66 fixes 2022-11-25 21:28:13 +01:00
e9618de67d improving external prog. calls 2022-11-25 19:26:04 +01:00
9745efa7d5 creating join 2022-11-25 19:25:41 +01:00
2e442acc3d fix routing with permissions 2022-11-20 13:50:53 +01:00
866b5416a4 Impl. routing error codes 2022-11-16 22:17:41 +01:00
71fe6219c8 update null serialization 2022-11-09 23:00:45 +01:00
ca5f5aa58e ? changes 2022-11-09 22:55:39 +01:00
92200f82b2 Merge branch 'develop' of https://github.com/Karaka-Management/phpOMS into develop 2022-11-06 18:32:28 +01:00
5f7bca33f7 fix workflow 2022-11-06 18:32:26 +01:00
ce8c46292c Merge branch 'develop' of https://github.com/Karaka-Management/phpOMS into develop 2022-11-06 18:27:37 +01:00
100e62929c update 2022-11-06 18:14:35 +01:00
34f53c50e3 test mssql service 2022-11-05 12:22:31 +01:00
2c892ade63 mssql fixes 2022-11-05 10:24:14 +01:00
34543e5d34 update mssql ip 2022-11-05 09:54:12 +01:00
eb85b49c40 fix CI 2022-11-05 02:01:09 +01:00
11f34bcccc inspection fixes 2022-11-05 01:38:55 +01:00
72cbfa19db Merge branch 'develop' of https://github.com/Karaka-Management/phpOMS into develop 2022-11-05 01:38:30 +01:00
1e900f77a5 update formatting and type hint 2022-11-04 20:39:20 +01:00
4f401bf2a8 fix function naming 2022-11-04 20:05:49 +01:00
bc3b9154e9 fix tests 2022-10-08 21:35:01 +02:00
bbad88d226 update actions NO_CI 2022-10-08 12:27:52 +02:00
9851eeb001 fix readmes 2022-10-01 22:29:33 +02:00
2d408874fa Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2022-10-01 18:04:33 +02:00
8396a6089d update workflows 2022-10-01 18:03:51 +02:00
6b6b28d922
Create dependabot.yml 2022-09-30 19:44:46 +02:00
9d7d48f424 github special case check 2022-09-30 19:17:28 +02:00
6459e61a63 debugging 2022-09-30 19:02:07 +02:00
06c15c4a09
Update main.yml 2022-09-30 18:49:06 +02:00
133d7ff102
Update main.yml 2022-09-30 18:41:54 +02:00
e0c3b4628d add debugging 2022-09-30 18:10:27 +02:00
aab71632c3 try to catch test server exceptions 2022-09-30 18:07:07 +02:00
ed2e2375b2 try to catch test server exceptions 2022-09-30 18:06:55 +02:00
01615d3df7 still trying to fix imap 2022-09-30 17:46:05 +02:00
064d5f2e85 Trying to fix presumably imap connection errors 2022-09-30 17:33:51 +02:00
dc09cbb703 fix imap connection error 2022-09-30 17:11:29 +02:00
f1114b2f0a phpstan fix 2022-09-30 17:04:27 +02:00
751ce51220 fix risky test 2022-09-30 16:56:44 +02:00
328e9c547e fix bugs 2022-09-30 16:29:51 +02:00
634cc3d505 test fixes 2022-09-30 15:41:54 +02:00
5cfa5f5a95 fix bugs 2022-09-30 14:29:21 +02:00
f3124aafdf test fixes 2022-09-30 14:14:41 +02:00
45f64a09aa fix test setup bug 2022-09-30 00:26:28 +02:00
4b03cd91f5 further fixes 2022-09-30 00:16:58 +02:00
152f2a39ea fix test errors 2022-09-30 00:03:17 +02:00
f2bc629fc0 test fixes 2022-09-28 16:41:17 +02:00
eb3449f308 check dependencies 2022-09-28 00:11:41 +02:00
6e6aa16f84 start fixing tests 2022-09-27 23:57:45 +02:00
c77874873c phpstan fixes 2022-09-27 21:23:30 +02:00
de0d70679b more fixes 2022-09-27 19:50:54 +02:00
4841e1538b minor fixes 2022-09-27 19:24:44 +02:00
8f161afcce more inspection fixes 2022-09-27 18:38:38 +02:00
d245e8d184 fixing phpstan errors 2022-09-27 18:08:15 +02:00
9e60c0e552 update php version 2022-09-27 17:44:29 +02:00
aa04922214 update configs 2022-09-27 17:41:01 +02:00
7a66e48aa5 limit validation 2022-09-27 17:35:05 +02:00
ca42a6df54
Update main.yml 2022-09-27 17:23:09 +02:00
ee363e07fc fix tokens 2022-09-27 17:10:23 +02:00
445006e9b4 fix typehint 2022-09-20 22:45:34 +02:00
d631e4ce62 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2022-09-09 21:00:47 +02:00
2612e1f862 fix statistics function during documentation update 2022-09-09 21:00:30 +02:00
Formatter Bot
7077ab29ea Automated formatting changes 2022-09-08 17:19:14 +00:00
7c8469c114 minor code style fixes 2022-09-08 19:18:16 +02:00
f4dcb64af0 change license 2022-08-20 11:57:50 +02:00
Formatter Bot
e204ff0c47 Automated formatting changes 2022-08-16 17:15:23 +00:00
84fb308b3a fix stupid asignments 2022-08-16 19:03:59 +02:00
87d07b3574 draft table search/filter impl. 2022-08-01 20:51:10 +02:00
d09b3db948 pull out iterator definition 2022-05-01 22:06:17 +02:00
cd35204f03 allow option overwrite in sort, with, limit 2022-05-01 22:05:41 +02:00
8c865bb0aa optimize views 2022-05-01 22:05:01 +02:00
35d13cd7db Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2022-04-24 23:13:52 +02:00
d4b116aa85 workflow drafting 2022-04-24 23:01:31 +02:00
4027a9159f fixes 2022-04-23 16:30:55 +02:00
edd4693111 doc fixes 2022-04-21 23:52:01 +02:00
Formatter Bot
3e79dc03d9 Automated formatting changes 2022-04-19 21:42:22 +00:00
d62475dc69 update php version 2022-04-19 23:37:09 +02:00
Formatter Bot
b4f61f760a Automated formatting changes 2022-04-18 20:42:11 +00:00
6bcd0c4bbe ical update 2022-04-18 22:39:00 +02:00
26e2e8a876 workflow fixes 2022-04-10 18:51:42 +02:00
3e50583065 workflow fixes 2022-04-10 18:22:03 +02:00
Formatter Bot
bc8c30052c Automated formatting changes 2022-04-10 16:09:45 +00:00
4da3c35cbf update composer 2022-04-10 18:04:27 +02:00
d77f090e33 update composer 2022-04-10 17:54:25 +02:00
3207946802 phpstan level fix 2022-04-06 18:52:56 +02:00
b2efd91008 static code analysis fixes 2022-04-05 20:01:46 +02:00
8dcc7feaa1 fix deprecated and disabled function defaults 2022-04-04 19:12:41 +02:00
9ae86275ff phpstan and phpcs fixes 2022-03-29 16:41:17 +02:00
e2b842c29d improve cli argument handling 2022-03-28 21:28:38 +02:00
c1fb9a31dc undo serialize deprecation 2022-03-26 14:59:56 +01:00
9f0a6233a0 revert serializable 2022-03-23 08:39:07 +01:00
a74d2e8a97 stupid changes 2022-03-23 08:34:54 +01:00
fb3988e72c fix deprecation 2022-03-22 18:14:57 +01:00
b1faa50caa fixed php 8.1 type bugs 2022-03-22 17:34:58 +01:00
97ad384589 handle null json 2022-03-22 16:32:18 +01:00
cab2628062 getRoute now returns the offsetted path by default 2022-03-19 08:15:04 +01:00
a2f067920c bug fixes from the day before 2022-03-19 00:02:44 +01:00
e25b309171 para fix 2022-03-18 19:51:46 +01:00
d63a71a8de fix test 2022-03-18 19:51:37 +01:00
143b39a5ee changed badly named permission type to permission category because type should only be read/write/... 2022-03-17 23:01:30 +01:00
c560be94ba always pass 2022-03-17 22:38:28 +01:00
b034c617fd fix limit/sort bug for has many elements 2022-03-17 18:30:11 +01:00
4cb31cc3ed fix async 2022-03-17 17:16:25 +01:00
a03fd72dbd generalize function type 2022-03-11 23:19:28 +01:00
f92947175c make route verb part of the abstract class 2022-03-11 23:19:08 +01:00
960fdfcfe9 allow to get arguments by index 2022-03-11 23:18:35 +01:00
c5cd5da5d9 fix cli routing 2022-03-11 23:18:00 +01:00
df89ee433e allow event trigger passing 2022-03-11 23:17:38 +01:00
c20021464c changed permissions to boolean flags 2022-03-11 23:17:08 +01:00
a3ee157bae impl. cli arguments 2022-03-11 23:16:55 +01:00
3e609e6041 add background execution option/flag 2022-03-11 23:16:35 +01:00
1d583a03ea impl. standard epsilon value 2022-03-11 23:16:16 +01:00
a7fc3812ae add pdf parser wrapper 2022-03-11 23:15:53 +01:00
7456a32a1f add user name rendering 2022-03-11 23:15:10 +01:00
288e9d62d6 udpate cli request 2022-03-11 23:14:51 +01:00
7ed21a1ec0 impl. standard epsilon value 2022-03-11 23:14:38 +01:00
755ee54f0c update cmd handling, fix bugs 2022-03-05 16:58:59 +01:00
a86685a04d added git configs 2022-03-05 16:58:20 +01:00
f157d05c00 fix name 2022-02-19 14:25:29 +01:00
516a506556 name fix 2022-02-19 14:16:38 +01:00
d859f287d5 fix name 2022-02-19 13:57:39 +01:00
263ea88951 autoformat 2022-02-13 23:58:36 +01:00
60e9e35892 add basic tesseract cli support 2022-02-13 23:58:18 +01:00
d4308ec916 remove unused param 2022-02-13 23:57:54 +01:00
625559977f image thresholding 2022-02-13 23:57:33 +01:00
fea0569020 image thresholding 2022-02-13 23:57:19 +01:00
f47d83a664 autofix 2022-02-12 21:18:13 +01:00
cb2877f45c draft neuralnet 2022-02-12 21:17:52 +01:00
eb9298ec98 improve docblock 2022-02-12 20:10:28 +01:00
d5fef266f5 add matrix cross3 and dot product 2022-01-29 20:51:25 +01:00
bf0dd44985 autoformat 2022-01-22 21:54:15 +01:00
169b5535d3 fix bugs 2022-01-22 21:53:38 +01:00
d20da74b77 merge 2021-12-19 20:26:16 +01:00
1e90a5ba9d continue datamapper bug fixes 2021-12-19 20:18:36 +01:00
Formatter Bot
89ae5950e4 Automated formatting changes 2021-12-11 10:58:10 +00:00
aa004569f5 new datamapper mostly implemented 2021-12-11 11:54:17 +01:00
b44aad18d1 fix router bug 2021-11-29 21:26:57 +01:00
3c464a1e21 fix line-ending 2021-11-29 20:07:33 +01:00
be1cdcf1ec fix tabs 2021-11-29 20:04:41 +01:00
e740bfbe3e formatting and minor fixes 2021-11-29 20:03:21 +01:00
77f099559b auto-fix 2021-11-28 20:02:55 +01:00
44ea04b2c6 impl. draft for new datamapper 2021-11-28 20:02:35 +01:00
162c30fb64 add ordertype 2021-11-28 20:02:00 +01:00
faf8423dd7 fix typo 2021-11-28 20:01:33 +01:00
6cd43859ec impl. mail functionality, some bug fixes and code style 2021-11-16 00:04:23 +01:00
bbab09b0ea add unit tests 2021-11-02 21:57:10 +01:00
05066c520e bug and media fixes 2021-10-29 14:49:55 +02:00
868390a7f3 remove var_dump 2021-10-26 14:43:20 +02:00
12b8eea76c fix ftp upload 2021-10-26 14:42:54 +02:00
5e63303b67 test fixes 2021-10-25 20:06:49 +02:00
Formatter Bot
d46276184a Automated formatting changes 2021-10-24 11:24:52 +00:00
892788ece2 get overall coverage to 76% 2021-10-24 13:18:08 +02:00
2cfcb24742 more tests and make classes final 2021-10-21 22:16:07 +02:00
9f8d074e84 sendmail check fix? 2021-10-15 00:14:59 +02:00
3b20d0c475 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2021-10-15 00:04:51 +02:00
def25c433f fix prefix 2021-10-15 00:04:31 +02:00
4a7de293ff build fixes 2021-10-15 00:03:20 +02:00
Formatter Bot
6e163187f4 Automated formatting changes 2021-10-14 21:52:08 +00:00
2a288de983 test fixes 2021-10-14 23:50:26 +02:00
8ec4d17ff7 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2021-10-13 18:21:44 +02:00
06c7f308e2 fix memcache regex search 2021-10-13 18:18:53 +02:00
Formatter Bot
747d40f1e7 Automated formatting changes 2021-10-12 14:21:08 +00:00
a8ebed1d3b test fixes 2021-10-12 16:19:46 +02:00
b53973157d try to fix some caching bugs memcached/redis 2021-10-12 00:08:55 +02:00
72b23f2928 fix bug with ms and s 2021-10-11 23:41:22 +02:00
534b325c24 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2021-10-11 23:29:08 +02:00
746b6ffc7a fix missing sendmail for mail 2021-10-11 23:28:41 +02:00
Formatter Bot
17453e225c Automated formatting changes 2021-10-11 21:08:53 +00:00
9d239ebd98 fix tests 2021-10-11 22:56:16 +02:00
3d7586f385 fix native function call phpcsfixer 2021-10-11 22:45:08 +02:00
Formatter Bot
90b24dbc87 Automated formatting changes 2021-10-11 20:26:59 +00:00
67fe4641e4 fix root namespace usage 2021-10-11 22:22:28 +02:00
Formatter Bot
4ce8879933 Automated formatting changes 2021-10-11 20:04:39 +00:00
ba7f68f69f fix phpstan and phpcs 2021-10-11 22:01:05 +02:00
6338db6631 fix build 2021-10-11 19:20:22 +02:00
f43df4c7c2 phpstan fixes 2021-10-10 16:07:06 +02:00
Formatter Bot
a42f662062 Automated formatting changes 2021-10-10 09:08:16 +00:00
fa7fb0f188 unit tests and bug fixes 2021-10-10 11:03:34 +02:00
894604c406 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2021-10-03 09:28:51 +02:00
b62b46ad3c fix class names and typos 2021-10-03 09:27:46 +02:00
Formatter Bot
56a11bf1db Automated formatting changes 2021-10-03 07:20:02 +00:00
0d63731697 phpcs, static and unit test fixes 2021-10-03 09:16:47 +02:00
d209c16831 bug fixes 2021-10-03 01:25:38 +02:00
9d6e431c3b unit test fixes 2021-10-02 22:42:46 +02:00
Formatter Bot
0d83f2a22b Automated formatting changes 2021-10-02 18:51:15 +00:00
002112fca4 test fixes and added more tests 2021-10-02 20:49:17 +02:00
2cf30d1073 remove test 2021-09-30 22:55:49 +02:00
4d0215580c move oauth to new branch 2021-09-30 22:24:54 +02:00
f5d41b0d81 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2021-09-30 22:15:05 +02:00
a4e7957dbb impl. tests 2021-09-30 22:14:37 +02:00
4accb7b716 impl. additional unit tests 2021-09-29 20:34:41 +02:00
Formatter Bot
463532ecc9 Automated formatting changes 2021-09-28 17:41:07 +00:00
5fb18505dc Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2021-09-28 19:39:31 +02:00
79c91d9895 rename module constants and fix some unit test bugs 2021-09-28 18:28:43 +02:00
d7e89a4a31 bug fixes 2021-09-28 10:19:37 +02:00
0df18d08e1 fix archives 2021-09-27 23:36:14 +02:00
82fd468519 fix zip unpack 2021-09-27 23:31:15 +02:00
Formatter Bot
579a936c5c Automated formatting changes 2021-09-27 21:19:54 +00:00
3828832230 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2021-09-27 23:18:31 +02:00
86029bc54f impl. todos or move to Project.md 2021-09-27 23:14:01 +02:00
9ae2cd45ed bug fixes 2021-09-25 14:48:54 +02:00
Formatter Bot
3c5c0c62b5 Automated formatting changes 2021-09-25 07:35:24 +00:00
e8cae23ca9 finalize app installation draft 2021-09-20 20:15:15 +02:00
Formatter Bot
ca537eda92 Automated formatting changes 2021-09-20 15:20:26 +00:00
99a9153a60
Update StatusAbstract.php 2021-09-20 17:19:26 +02:00
a0fbf00580
Update StatusAbstract.php 2021-09-20 17:18:53 +02:00
450b36aa96
Update StatusAbstract.php 2021-09-20 17:18:31 +02:00
31efb58ef3
Create StatusAbstract.php 2021-09-20 17:18:13 +02:00
Formatter Bot
6f8b771ab6 Automated formatting changes 2021-09-19 17:56:35 +00:00
99df0e971e september update 1 2021-09-19 19:50:15 +02:00
420c34aec2 mostly docs 2021-08-29 10:50:31 +02:00
eac68f4185 bug fixes and template adjustments 2021-07-31 17:20:50 +02:00
Formatter Bot
269cd5cab8 Automated formatting changes 2021-07-19 19:37:45 +00:00
76b84d714e Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2021-07-19 21:35:24 +02:00
522db1d462 fix bugs and start impl. additional functions 2021-07-17 21:12:01 +02:00
Formatter Bot
8ced49783e Automated formatting changes 2021-07-15 20:01:17 +00:00
e2f6061fa7 implement todos 2021-07-15 21:51:30 +02:00
f44d1c7983 fix formatting 2021-07-04 18:25:57 +02:00
580460dc11 fix phpstan/phpcs 2021-06-26 14:38:08 +02:00
5ed284a1d1 pass app to installer 2021-06-23 23:59:55 +02:00
cd50ceb819 add bool data request 2021-06-23 23:59:34 +02:00
db0908bad8 fix app setup 2021-06-23 23:59:12 +02:00
d62222507a set specific pwd algo 2021-06-23 23:58:50 +02:00
930f7c8e86 add indirect relations 2021-06-23 23:57:28 +02:00
Formatter Bot
3226150ee5 Automated formatting changes 2021-06-05 09:10:27 +00:00
888745d3e5 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2021-06-05 11:08:49 +02:00
2e4af70139 bug fixes 2021-06-05 11:02:50 +02:00
5b9315bf71 bug fixes with unit testing 2021-05-28 22:22:45 +02:00
Formatter Bot
9fd6827605 Automated formatting changes 2021-05-28 18:35:38 +00:00
47767eea0d fix 2021-04-24 16:21:10 +02:00
12308efbed
Add return type NO_CI 2021-04-22 16:45:29 +02:00
2a07ba2f39
Fix permission check NO_CI 2021-04-22 16:44:31 +02:00
672ab973c8
Fix permission check NO_CI 2021-04-22 16:35:03 +02:00
f25cbe3a7a
Fix test case NO_CI 2021-04-22 16:30:50 +02:00
471e1f0099
Fix type NO_CI 2021-04-22 15:47:42 +02:00
d03848cc3d
Fix docblock NO_CI 2021-04-22 15:40:41 +02:00
0c93056d66
Equals sign alignment fixed NO_CI 2021-04-22 15:35:14 +02:00
457340668d
Update MbStringUtilsTest.php 2021-04-22 14:36:22 +02:00
Formatter Bot
c97b516378 Automated formatting changes 2021-04-04 15:16:03 +00:00
67f969a6b8 many fixes and expands and module expansions 2021-04-04 17:10:53 +02:00
02313d3a33 draft ::with() function for models 2021-03-11 21:23:41 +01:00
Formatter Bot
3c2cd68edf Automated formatting changes 2021-03-07 20:44:06 +00:00
20a8078a2c spellchecking 2021-03-07 21:37:08 +01:00
f3a4ce2ca8 fix php version 2021-03-05 20:59:24 +01:00
0348b0c91e fix event trigger string 2021-03-05 20:59:14 +01:00
90eaa66e9c bug fix 2021-03-05 20:58:52 +01:00
4b33cb660f get referer 2021-03-05 20:58:22 +01:00
fe2c5676e1 auto format decimals 2021-03-05 20:58:08 +01:00
f3cbc2051a fix event manager 2021-03-05 20:57:41 +01:00
9272af316b fix formatting/debugging 2021-02-20 21:18:12 +01:00
333741d1ef mode changes 2021-02-20 10:59:06 +01:00
122d48d493 fix handling .. and \ in path string 2021-02-12 17:59:25 +01:00
8e8b40c70e impl. todos 2021-02-09 22:56:16 +01:00
4a1e128122 update composer 2021-02-08 23:00:57 +01:00
c2a3797b33 fix word/spreadsheet icon rendering 2021-02-08 18:48:16 +01:00
Formatter Bot
85c9e50390 Automated formatting changes 2021-02-06 12:51:28 +00:00
244672c64e Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2021-02-06 13:47:19 +01:00
22cd674189 improve country handling 2021-02-06 13:47:12 +01:00
Formatter Bot
b61ffa7235 Automated formatting changes 2021-01-31 16:16:50 +00:00
acedec0db1 re-add php-cs-fixer 2021-01-31 17:15:46 +01:00
bc7fe194c7 better sql error handling and new request data get function 2021-01-23 12:29:02 +01:00
b6cba39abf fix tests 2021-01-01 18:47:54 +01:00
69ff0e0035 test fixes 2020-12-26 13:19:20 +01:00
a5a9d20941 more mail bug fixes 2020-12-23 20:57:23 +01:00
8fdf9f96e7 fix test bugs 2020-12-23 20:16:33 +01:00
51c9d71e02 use & instead of , for fragments 2020-12-20 20:01:59 +01:00
04c1927c96 Draft module status changes (route changes) 2020-12-20 20:01:35 +01:00
f619b2eee9 optimze if 2020-12-20 20:00:00 +01:00
0646bec94f Expand cache interface 2020-12-20 19:59:39 +01:00
291620b1f0 Impl. temp password 2020-12-20 19:58:46 +01:00
b7131f34e1 continue drafting mail handler 2020-12-19 20:31:52 +01:00
91fde08f52 add multiple fragment support 2020-12-19 20:31:34 +01:00
7981adf359 fix member exposing 2020-12-19 20:30:19 +01:00
7443963582 fix bug with missing ? and multiple fragments 2020-12-19 20:29:52 +01:00
a392d44799 rewind file 2020-12-19 20:29:01 +01:00
cadc00fd3a fix type hint 2020-12-19 20:28:51 +01:00
59417c16a9 fix type hint 2020-12-19 20:28:40 +01:00
d2cb300072 Add trigger to audit 2020-12-19 20:28:30 +01:00
fe58dd74e8 fix relation bug 2020-12-19 20:27:58 +01:00
f5e12ba33d add root namespace 2020-12-12 18:35:05 +01:00
77b26ad788 draft mail handler 2020-12-12 18:23:03 +01:00
0cfe3a45bd Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2020-12-06 18:45:40 +01:00
9a3d200253 fix templates 2020-12-06 16:14:42 +01:00
65fd3c14bd
Update main.yml 2020-12-06 11:30:01 +01:00
4b1d77cc86 tpl fixes, dont use printHtml for none-string types 2020-12-06 11:13:19 +01:00
f5ad4345bb fix unit tests 2020-12-05 22:45:51 +01:00
3fc7c0c233 try to fix static return 2020-12-05 21:58:26 +01:00
440d00ec6b try to fix static return 2020-12-05 21:57:38 +01:00
4a9233c949 try to fix static return 2020-12-05 21:57:33 +01:00
710ff5f7d3 phpcs fixes 2020-12-05 21:39:55 +01:00
fb295292be update composer and fix bugs 2020-12-05 19:39:56 +01:00
863d69af78 make framework test more independent 2020-12-04 21:08:15 +01:00
4dff9b5357 use trait 2020-12-04 19:41:53 +01:00
a13c48dd8f fix typo 2020-12-04 19:36:36 +01:00
48d7bb8dfd fix include 2020-12-04 19:36:04 +01:00
1870113eb0 fix tests 2020-12-04 19:26:39 +01:00
8f4e7432ff update composer 2020-12-04 19:09:36 +01:00
Formatter Bot
5ba685e12b Automated formatting changes 2020-12-04 12:08:47 +00:00
8641d7610c
Update composer.json 2020-12-04 13:07:58 +01:00
400a2d50d4 bump php version 2020-12-03 23:11:15 +01:00
fdd8518474 bump php version 2020-12-03 23:07:33 +01:00
0f1a799014 implement php 8.0 types 2020-12-03 22:39:56 +01:00
2bfb2c1329 start impl. php 8.0 typehints 2020-12-03 20:49:09 +01:00
d35b600cd3 prepare for php 8.0 2020-11-30 22:21:50 +01:00
e78da93a1a fix recursive directory iterators 2020-11-30 21:33:18 +01:00
d8ea389a70 start fixing tests for php 8 2020-11-30 21:22:28 +01:00
6ac2d4d0e8 fixes 2020-11-30 21:13:06 +01:00
1e19f72fc4 fix datamapper bugs 2020-11-29 18:29:35 +01:00
6443ab6c14 fix tests 2020-11-28 19:26:40 +01:00
1ed4f3f5e2 phpcs fixes 2020-11-28 00:13:12 +01:00
aaf34cd373 phpstan fixes 2020-11-27 22:56:16 +01:00
f9e71e5a9e minor structure optimizations 2020-11-26 21:57:58 +01:00
843d97c632 fix todos/move to todo list 2020-11-26 20:50:18 +01:00
b57e6ca305 remove webinterface 2020-11-25 01:00:27 +01:00
ba7737d0ad autofixes 2020-11-24 18:44:22 +01:00
86d62a1bb5 remove some getter/setter 2020-11-24 17:31:21 +01:00
1d5b727465 fix uri building bug and conditional loading bug 2020-11-15 21:12:05 +01:00
01a2e984ad Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2020-11-10 22:17:35 +01:00
2589f91995 add email rng 2020-11-10 22:08:32 +01:00
9aa9fa9abe simplify getLanguage call in request 2020-11-10 22:08:07 +01:00
5cc7030b85 auto format 2020-11-04 20:42:06 +01:00
2a3d273f99 added get by parent function 2020-11-04 20:41:47 +01:00
6a6351a275 search for include path 2020-10-31 19:38:51 +01:00
0bec263d78 allow custom template extension 2020-10-29 22:30:07 +01:00
fc56af4ff1 fix missing default bug 2020-10-29 22:29:48 +01:00
5d5796b8fb add missing country 2020-10-29 22:29:31 +01:00
c0a46b778a fix depreciation spelling 2020-10-29 22:29:05 +01:00
Formatter Bot
33cfc8e4d8 Automated formatting changes 2020-10-25 22:15:36 +00:00
8e225141ad add languages 2020-10-25 23:06:41 +01:00
553a17edaf fix event triggering with regex 2020-10-25 23:06:28 +01:00
d7be58a4fe make lorem ipsum words public const 2020-10-25 23:05:54 +01:00
7fe9e1f418 remove debugging point 2020-10-25 10:58:15 +01:00
2bcf7b78a4 remove empty url query parameters 2020-10-24 23:32:24 +02:00
5aa0276f11 cs and phpstan fixes 2020-10-24 17:53:54 +02:00
988468bc82 fix packing path for dir 2020-10-22 20:24:23 +02:00
cdd21c7a23 fix test 2020-10-22 19:43:13 +02:00
ce1678626d zip packing test 2020-10-22 19:17:02 +02:00
d620bed337 try to fix zip packing 2020-10-22 19:05:35 +02:00
c49ce8a690 fix default country 2020-10-22 18:54:32 +02:00
5fc7be78c1 fix address/location test 2020-10-22 18:46:07 +02:00
98a7ccbae8 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2020-10-21 23:21:18 +02:00
Formatter Bot
7968f39f10 Automated formatting changes 2020-10-21 20:33:57 +00:00
c2334057b3 change self/external behaviour / invert it! 2020-10-21 22:32:33 +02:00
e0286b2392 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2020-10-21 19:36:49 +02:00
3df0d1463a update path fixes 2020-10-21 19:36:37 +02:00
3e0d7ec68b add db formats 2020-10-21 19:31:42 +02:00
5892819542 allow dynamic d parameter population 2020-10-18 20:50:07 +02:00
c2f025e59d set default country 2020-10-18 20:49:19 +02:00
b34595bfa5 autofixes 2020-10-18 20:48:40 +02:00
306f57c4d0 add todos 2020-10-18 20:48:19 +02:00
aaa8d9d533 fix invalid class loading 2020-10-18 20:47:50 +02:00
8fc34ef870 add sqlsrv and fix system escaping 2020-10-11 18:57:21 +02:00
fd211cd949 autofixes 2020-10-11 15:37:57 +02:00
d1e8a0800f impl. sqlsrv and fix 64bit bugs 2020-10-11 15:37:20 +02:00
Formatter Bot
b2415446a1 Automated formatting changes 2020-10-10 19:33:10 +00:00
e09ac0686e add tests 2020-10-10 21:28:38 +02:00
27f7f9a1dd fix @covers 2020-10-09 00:20:25 +02:00
7587f496d3 add test 2020-10-08 20:19:13 +02:00
55f79f7c01 fix file_exists replacement 2020-10-08 17:52:29 +02:00
9fe5c84b47 fix packing bug with zip 2020-10-08 17:32:30 +02:00
74ed9b9ef7 fix file checks 2020-10-08 17:06:25 +02:00
64f498588f fix source check 2020-10-08 15:55:45 +02:00
00d3f3d947 clear file cache 2020-10-08 15:50:34 +02:00
e9426bf18a fix dir check 2020-10-08 15:37:11 +02:00
06070dcac2 fix is_* check 2020-10-08 15:34:05 +02:00
005f169e48 fix tests and replace file_exists 2020-10-08 15:12:24 +02:00
abdfa6c6eb add param description 2020-10-07 19:06:39 +00:00
1cb7a1ed77 Add search and comparison functionality 2020-10-07 20:57:08 +02:00
33db2fd2da Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2020-10-06 21:53:44 +02:00
4742d437dd fix header status code bugs 2020-10-06 21:49:42 +02:00
7b06f33496 fix float limits 2020-10-06 21:49:29 +02:00
ef2ad3d19f fix delete bug 2020-10-06 21:49:12 +02:00
Formatter Bot
9406856e59 Automated formatting changes 2020-10-06 12:28:10 +00:00
77bbb3f7a7 Add Oauth2 tests 2020-10-06 14:26:36 +02:00
daebfe1c57 autofixes 2020-10-06 11:35:47 +02:00
ef35a22f93 impl. more tests 2020-10-06 11:35:34 +02:00
Formatter Bot
ce40682a3b Automated formatting changes 2020-10-05 23:36:37 +00:00
67ca803026 fix tests 2020-10-06 01:32:47 +02:00
58c49080c8 improve tests 2020-10-06 00:50:24 +02:00
f7c5233d28 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2020-10-05 19:33:31 +02:00
37b0c85a7a autofixes 2020-10-05 19:29:32 +02:00
3c69c2c209 Add tests e.g. preloader 2020-10-05 19:28:57 +02:00
Formatter Bot
d7deaf139a Automated formatting changes 2020-10-03 21:08:56 +00:00
14fcafc9a5 impl. more tests 2020-10-03 22:34:58 +02:00
2f37ad1200 ftp directory tests working 2020-10-03 13:56:28 +02:00
f77ab5e980 continue file impl. 2020-10-03 13:34:36 +02:00
be99c96ac6 continue file test impl. 2020-10-03 11:21:06 +02:00
6adf0fda8e draft ftp dir tests 2020-10-03 10:46:03 +02:00
4f463ed26e impl. local directory tests 2020-10-02 21:18:13 +02:00
2c49d9aee9 test impl. and code coverage improvements 2020-10-02 20:02:04 +02:00
Formatter Bot
670be4fcf0 Automated formatting changes 2020-09-27 14:53:26 +00:00
7db416f718 auto fix 2020-09-27 16:50:17 +02:00
96f8f25d6e impl. tests 2020-09-27 16:49:19 +02:00
290a997444 use foreach initialized var 2020-09-26 16:52:29 +02:00
41e2e10540 phpstan fix 2020-09-26 15:20:32 +02:00
a5ba70d40e update and fix phpunit config 2020-09-26 14:28:02 +02:00
340fdc4943 autoformat 2020-09-26 12:51:46 +02:00
abf0c43582 package namespace fix 2020-09-26 12:16:42 +02:00
781366694c some minor cleanup, still not implemented 2020-09-26 12:08:31 +02:00
49135aefab fix DateTimeImmutable typehint 2020-09-26 11:22:57 +02:00
ad28da979e
NO_CI 2020-09-25 15:58:20 +02:00
7a3b8aab82
NO_CI 2020-09-25 15:52:59 +02:00
7b1e7ac1ae
NO_CI 2020-09-25 15:52:23 +02:00
Formatter Bot
29080bd731 Automated formatting changes 2020-09-19 19:28:40 +00:00
b812866d87 start impl. legal entities 2020-09-19 21:25:44 +02:00
Formatter Bot
793efdfb45 Automated formatting changes 2020-09-18 19:27:39 +00:00
e98d649876 impl. tests and graph 2020-09-18 21:25:29 +02:00
f467b598a3 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2020-09-17 18:54:17 +02:00
016af92a05 autoformat 2020-09-17 18:51:21 +02:00
74c3c456b9 improve tests 2020-09-17 18:50:56 +02:00
793e7a5f15 continue oauth client impl. 2020-09-17 18:50:25 +02:00
Formatter Bot
b779e21375 Automated formatting changes 2020-09-13 18:41:31 +00:00
d2ccc2d15e add test for invalid item 2020-09-13 20:38:03 +02:00
c15c9b8b09 JIT db connection implemented 2020-09-12 23:13:58 +02:00
0a11f2d36b fix DateTime -> DateTimeImmutable 2020-09-12 22:13:02 +02:00
80dee41e9e Add file size formatting 2020-09-12 22:12:33 +02:00
7275e7b475 autofixes 2020-09-12 22:12:16 +02:00
4efa10c3e0 impl. tests for routing 2020-09-12 22:12:00 +02:00
bd39681b54 use datetimeimmutable 2020-09-10 20:44:07 +02:00
4c1384f64b fix typehint 2020-09-10 20:40:13 +02:00
bea2d1ed0b implement immutable datetime 2020-09-10 20:18:02 +02:00
6035870c1f add date time immutable 2020-09-06 21:12:33 +02:00
ace6e49380 test improvements 2020-09-02 20:39:14 +02:00
b084791809 improved tests and test docs 2020-09-01 23:51:59 +02:00
Formatter Bot
bd97cee551 Automated formatting changes 2020-09-01 19:01:54 +00:00
88541106b7 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2020-09-01 20:58:36 +02:00
b419139a45 manual cs fixes 2020-09-01 20:57:48 +02:00
Formatter Bot
c8f1b443dd Automated formatting changes 2020-09-01 10:52:10 +00:00
9dd26d3bdf
Update ModuleAbstractTest.php 2020-09-01 12:51:25 +02:00
Formatter Bot
bf9ef7b47d Automated formatting changes 2020-09-01 05:43:41 +00:00
28c9ec6a6c fix const alignment 2020-09-01 07:38:03 +02:00
463b2a6558 improve autofix 2020-08-31 23:14:57 +02:00
593cc1c105 fix extra blank lines 2020-08-31 22:54:13 +02:00
a559cb4e2e php cs autofix 2020-08-31 22:30:49 +02:00
9f3730c11c improve cs fixer command 2020-08-30 20:14:54 +02:00
71bb333aa4 autofixes 2020-08-30 20:13:11 +02:00
1826cc865b improve php-cs-fixer rules 2020-08-29 17:21:30 +02:00
f0a70805c6 update composer 2020-08-29 16:10:48 +02:00
018fbd3771 fix permission handling in routing and permission check 2020-08-11 20:37:15 +02:00
16961aaff6 fix array mapping bug 2020-07-31 18:40:30 +02:00
69728b23de inspection fixes 2020-07-31 18:13:59 +02:00
45507970b9 fix fix audit log creation 2020-07-31 15:38:20 +02:00
7c3811e624 update composer 2020-07-31 15:15:53 +02:00
479c9fff69 don't parse uris without {} elements 2020-07-31 15:15:39 +02:00
568f3fab4b added hashing of strings to ints 2020-07-31 00:15:19 +02:00
e736214417 optimize uri building 2020-07-30 21:26:30 +02:00
2177024fdc cache server headers 2020-07-30 21:26:07 +02:00
f554feae82 handle nullmodule function calls 2020-07-29 23:52:03 +02:00
8477cbe90e Add invalidation functionality 2020-07-29 21:49:49 +02:00
36c8d6ac5d add default mime 2020-07-29 20:56:38 +02:00
86d3c10b05 continue with emaill impl. 2020-07-29 20:56:22 +02:00
fc39d6d452 autofix 2020-07-23 20:50:43 +02:00
013ce912f9 optimize module loaded 2020-07-23 20:50:19 +02:00
a91ee19ff8 draft alter functionality 2020-07-22 09:50:12 +02:00
Formatter Bot
e697b0b1bd Automated formatting changes 2020-07-11 18:29:32 +00:00
3e77b4505c Add tests and mark incomplete tests 2020-07-11 20:26:01 +02:00
efd76ef4c2 start implementing basic Ai algorithms 2020-07-11 20:25:42 +02:00
29e448c3bd adjust conditional impl. This now allows to use conditionals without a column reference 2020-07-05 22:09:39 +02:00
644af71b73 continue oauth structuring NO_CI 2020-07-04 17:49:05 +02:00
be11b8359d add 'copyright' info for JAMA 2020-07-04 17:47:27 +02:00
53657299a7 fix creating conditional elements 2020-07-04 17:43:33 +02:00
bb805a11fe autoformat 2020-06-25 22:06:10 +02:00
a476ead7dd created customer value 2020-06-25 22:05:52 +02:00
c59b82490c added simple svg maps 2020-06-20 20:26:02 +02:00
c24d5b9e70 try to read on default NO_CI 2020-06-18 20:00:16 +02:00
27ca410b86 fix test bug 2020-06-14 15:12:57 +02:00
44d663d176 implement article affinity analysis 2020-06-14 14:54:43 +02:00
d556756283 split more population/sample calculations 2020-06-14 13:22:12 +02:00
ad2634e32a implemented pagerank algorithm 2020-06-14 00:08:16 +02:00
9947c203fb fixed bug with null models 2020-06-13 15:16:03 +02:00
452e541ecd fix bug where nullmodels would break updating 2020-06-12 18:21:16 +02:00
1cb038fbc2 fix update bug/depth. Update should be deeper than just 1 level 2020-06-12 17:40:24 +02:00
0cee08b087 fix broken getForArray implementation 2020-06-11 23:39:19 +02:00
b7cb3c6a7c support different comparison operators 2020-06-11 12:28:53 +02:00
e8b91fac09 fix bug where relations were still used for depth parameter 2020-06-11 10:52:05 +02:00
d2ab4feda0 fix cs 2020-06-11 09:39:08 +02:00
a2d92442b6 re-add populateIterable, apperently it is used :( 2020-06-10 22:47:10 +02:00
75df581156 fix bug where caching didn't consider the depth of the cached model, however it feels now slower 2020-06-10 21:49:48 +02:00
010b63b438 call methods as methods and not as static functions 2020-06-09 22:59:25 +02:00
7646f8a909
Optimize ignored default paths NO_CI 2020-06-09 15:42:13 +02:00
ddb6099db2 fix test bug 2020-06-08 23:32:20 +02:00
e5d32ec503 add some todos and thoughts about datamapper improvements 2020-06-08 23:28:52 +02:00
2ef8f17eb2 add conditionals filter for specific models 2020-06-08 22:39:59 +02:00
50743fecf0 fix tests 2020-06-08 18:20:24 +02:00
3801c29cf6
Fix cs NO_CI 2020-06-08 09:49:45 +02:00
360d0249b1
Fix cs NO_CI 2020-06-08 09:49:33 +02:00
944c947e3b
Fix cs NO_CI 2020-06-08 09:49:23 +02:00
918659c3ea
Fix cs NO_CI 2020-06-08 09:49:06 +02:00
3db14eb5b6 make db connection throw less exceptions 2020-06-07 22:24:24 +02:00
a0bb408b6a autoformat 2020-06-07 13:40:37 +02:00
358d981c2b don't run join queries again in fillRelation 2020-06-07 13:40:21 +02:00
Formatter Bot
b193159441 Automated formatting changes 2020-06-05 07:52:31 +00:00
ebd709d4cb
impl. early return 2020-06-05 09:51:47 +02:00
50ca46b5a9 fix ip logging bug 2020-06-03 22:11:52 +02:00
9b3e8960bd autoformat 2020-05-31 22:49:17 +02:00
42f2cbbe7e add ip to auditor 2020-05-31 22:49:05 +02:00
eb73cc4027 make tables tabable 2020-05-31 18:03:29 +02:00
f23995005c add copyrights 2020-05-30 15:38:32 +02:00
e2554a7257 fix fragment uri bug 2020-05-24 09:37:01 +02:00
5ad647c975 fix url building 2020-05-23 10:33:12 +02:00
a198d13a5f fix create parameters 2020-05-22 23:53:28 +02:00
96bf2572a0 avoid test error on 32bit systems 2020-05-22 22:53:59 +02:00
6bc337e23a fix test after settings pull out 2020-05-22 21:43:29 +02:00
0dd51a6f38 fix return 2020-05-22 17:47:19 +02:00
f4b061ee8a add issue information 2020-05-22 17:32:48 +02:00
61dada268a
Remove 8.0 tests 2020-05-22 14:53:56 +02:00
Formatter Bot
123bcc0559 Automated formatting changes 2020-05-22 12:50:54 +00:00
8ae435998f
Use setcookie options array 2020-05-22 14:50:05 +02:00
580db7a9d6
Fix member variable usage NO_CI 2020-05-22 14:14:34 +02:00
d613d747fc
Fix typo 2020-05-22 14:11:00 +02:00
aa95b145d1
Fix type NO_CI 2020-05-22 14:09:42 +02:00
566cfaa124
Fix EOL ; 2020-05-22 14:05:38 +02:00
3019a5fb10
Use app settings handler 2020-05-22 14:01:06 +02:00
9b184d3df3
settings dependency injection 2020-05-22 13:55:21 +02:00
b508eb11fd
Use framework account 2020-05-22 13:40:07 +02:00
b87930b309
fix sed path? 2020-05-22 13:32:01 +02:00
fb4c9deca7
Fix relative path 2020-05-22 13:22:29 +02:00
957453f4c7
Exclude volume and maybe groups from tests 2020-05-22 13:11:03 +02:00
b94f55cf25 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2020-05-10 10:53:45 +02:00
0bc4abc285 fix tests and gamma impl 2020-05-10 10:49:56 +02:00
Formatter Bot
981472382a Automated formatting changes 2020-05-09 15:28:58 +00:00
2070985e32 test and cs fixes 2020-05-09 17:27:03 +02:00
9bed188175 fix uri parsing with fragment 2020-05-07 19:30:37 +02:00
2379a8a09f fix uri factory test 2020-05-07 18:55:28 +02:00
7834d078b9 fix significance bug fix 2020-05-06 21:24:39 +02:00
7be395233c unit test fixes, phpstan fixes, phpcs fixes 2020-05-06 21:12:20 +02:00
5e04905b8e autoformat 2020-05-04 22:41:13 +02:00
b9fd2d0760 start impl. more business metrics 2020-05-04 22:41:05 +02:00
f66b5f1b9f autoformat 2020-05-04 22:40:46 +02:00
89e645a0cd impl. helper functions for easier use 2020-05-04 22:40:35 +02:00
3026fec00c continue impl. of distributions/stochastics/statistics 2020-05-04 22:39:48 +02:00
4ec4e95819 continue impl. of distributions/stochastics/statistics 2020-05-04 22:39:21 +02:00
131701195f fix query param encoding 2020-05-02 21:02:35 +02:00
3550b6a75a allow different theme during install 2020-04-27 19:58:26 +02:00
0420690853 add view hasData test 2020-04-25 11:03:04 +02:00
b6ea99b75c Add function to check data 2020-04-24 18:08:12 +02:00
86e8ae40de phpcs fixes 2020-04-19 10:39:21 +02:00
308261b2be cs fixes 2020-04-19 01:25:29 +02:00
b1ded69873 fix mysql db 2020-04-19 01:20:45 +02:00
Formatter Bot
583a7d3465 Automated formatting changes 2020-04-18 20:52:41 +00:00
bbdd04b36e add tests and fix bugs 2020-04-18 18:33:48 +02:00
20a45ef0c8 make null models final 2020-04-13 17:33:31 +02:00
c003aae57f autofixes 2020-04-13 10:44:10 +02:00
2c9d8fe6aa continue mail implementation 2020-04-13 10:43:59 +02:00
739c92c87f update phpstan version 2020-04-12 15:56:44 +02:00
d40ed903a5 continue mail implementation 2020-04-12 15:51:56 +02:00
d2e553643b fix exception typo 2020-04-11 21:43:02 +02:00
71100a4634 remove old exception 2020-04-11 21:39:01 +02:00
afe83cb82c autofix 2020-04-11 21:31:43 +02:00
22a63a2c32 split string utils and mb_string utils 2020-04-11 21:31:28 +02:00
12a4880f16 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2020-04-11 19:09:40 +02:00
76f4831836 autoformat 2020-04-11 19:09:23 +02:00
340ea049eb continue mail implementation 2020-04-11 19:09:13 +02:00
Formatter Bot
896d127a07 Automated formatting changes 2020-04-11 16:23:06 +00:00
1ec7e62756 continue implementing mail 2020-04-11 18:21:02 +02:00
Formatter Bot
dc02763fd3 Automated formatting changes 2020-04-05 15:41:19 +00:00
2b6cd1d21b continue implementing mailing 2020-04-05 17:36:29 +02:00
c35bccd8c0 fix issue repo 2020-04-05 17:08:51 +02:00
96dee76466 add charset enum 2020-04-05 17:08:04 +02:00
d5643868b6 add todo/question for global conditionals 2020-03-31 19:00:58 +02:00
9e96b89aa0 fix relation population 2020-03-31 18:23:46 +02:00
3997d9563e fix ownsOne and belongsTo hasMany relationships 2020-03-30 22:12:49 +02:00
ee06a96792 fix function return type hint cs 2020-03-29 12:50:25 +02:00
a72e781e02 Don't load default value if default value is not set 2020-03-28 17:26:51 +01:00
e83574a452 fix db bugs 2020-03-28 17:16:05 +01:00
7300b52d25 bugfix datamapper joins 2020-03-28 16:22:32 +01:00
0d087399bc cs fix 2020-03-25 19:47:37 +01:00
c720655d3f fix unit tests 2020-03-25 19:30:48 +01:00
3b13170a01 remove todo comment 2020-03-24 19:49:21 +01:00
7412a2cc0a fix conditional value type 2020-03-24 18:02:00 +01:00
f6436911f1 fix it language 2020-03-22 19:25:15 +01:00
8fb8659062 add timezone support 2020-03-22 19:09:05 +01:00
862da62226 implement localization 2020-03-22 18:42:34 +01:00
199b13ad75 optimize model selection 2020-03-22 17:06:27 +01:00
Formatter Bot
4ebc825b16 Automated formatting changes 2020-03-15 08:36:08 +00:00
5ba3ac9dd9 fixes Orange-Management/phpOMS#239 2020-03-15 09:29:04 +01:00
b6c4f1e4bc fix phpstan 2020-03-14 20:32:16 +01:00
0e5e967920 fix phpcs 2020-03-14 20:07:03 +01:00
dcfc61e7a9 fix findquery 2020-03-14 19:50:13 +01:00
d81bf80ada bug fixes after datamapper changes 2020-03-14 17:58:43 +01:00
7a5fad6659 fix whitespace 2020-03-14 09:47:09 +01:00
e7e298620d Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2020-03-14 00:18:03 +01:00
489752602f autofix 2020-03-14 00:17:17 +01:00
7163328a59 closes ##73 2020-03-14 00:17:07 +01:00
13326b6aea remove unused keys 2020-03-14 00:07:57 +01:00
bd927133d7 fix where query usage 2020-03-14 00:06:33 +01:00
b1e3eac74c start re-implementing conditional handling 2020-03-13 23:57:42 +01:00
Formatter Bot
61b816fcd7 Automated formatting changes 2020-03-13 22:34:19 +00:00
250bb48c9c autofix 2020-03-13 23:32:09 +01:00
4937fdb9f7 fixes #220 and fixes #102 2020-03-13 23:31:58 +01:00
3b740eae3c autofix 2020-03-12 18:15:51 +01:00
686d09a599 Fix dependency resolution 2020-03-12 18:15:32 +01:00
3b24e6c3d7 remove db prefix 2020-03-12 18:11:43 +01:00
3439fd57ff remove db prefix 2020-03-12 18:11:04 +01:00
b2f17234fa remove db prefix 2020-03-12 18:10:03 +01:00
1fdb93968a autofix 2020-03-07 19:49:16 +01:00
e5baf46dce optimize code readability and perforamnce 2020-03-07 19:48:58 +01:00
2a8ece6fcc Type and cs fixes 2020-03-07 00:23:22 +01:00
55182c4138 fixes #222 2020-03-06 23:12:59 +01:00
3f68bbad63 Started implementing #222 read is already working 2020-03-06 23:09:57 +01:00
e16ad97838 phpcs fix 2020-03-05 22:51:41 +01:00
5ad4c617c0 add todo 2020-03-05 22:34:10 +01:00
c3f4ba80bb remove todos #224 and #212 2020-03-05 22:15:09 +01:00
1594a88daf fixes #224 and fixes #212 2020-03-05 20:37:03 +01:00
5048008be6 theoretical bug fixes and style improvements 2020-03-04 00:08:50 +01:00
23e28feae2 start working on #212 2020-03-03 22:28:37 +01:00
4b1e89a7d8 improve issue templates 2020-03-03 20:22:36 +01:00
a11053db54 remove segfault debug 2020-03-03 10:17:56 +01:00
9dfc11c033 autoformat 2020-03-03 10:16:44 +01:00
9fde93c0c4 fix typehint 2020-03-03 10:16:31 +01:00
f65032e4c9 autofix 2020-03-03 10:09:55 +01:00
ade50ca213 add logging for github segfalt 2020-03-03 10:09:45 +01:00
e584c1119b optimize coverage for github actions 2020-03-03 09:32:42 +01:00
57ec39bb51 merge 2020-03-02 22:52:22 +01:00
04e979911c autofixer 2020-03-02 22:50:15 +01:00
39db344ebd php cs and stan fixes 2020-03-02 22:49:33 +01:00
188a993d84 update phpstan 2020-03-02 17:17:19 +01:00
Formatter Bot
7404634af6 Automated formatting changes 2020-03-01 18:33:21 +00:00
b99ab9d138 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2020-03-01 19:32:22 +01:00
08080d4b99 remove empty lines 2020-02-28 18:53:06 +01:00
a2a70e28eb phpstan fixes and install bug 2020-02-27 19:01:55 +01:00
25f7f534d5 install default theme 2020-02-26 21:26:32 +01:00
Formatter Bot
34a0618d59 Automated formatting changes 2020-02-26 19:53:14 +00:00
fc68a96592 optimize app isntall 2020-02-26 19:43:25 +01:00
d1d300eedd allow module app install 2020-02-26 19:28:06 +01:00
62cd92710b update phpstan version 2020-02-25 22:47:00 +01:00
5ba452d12f update composer 2020-02-25 22:28:46 +01:00
808dd9dffc minor cs fixes 2020-02-25 22:15:28 +01:00
e89881e589 add test file 2020-02-25 21:45:04 +01:00
f24da643ec fix trim 2020-02-25 21:05:23 +01:00
c79a711fd3 improve doc 2020-02-25 20:40:21 +01:00
Formatter Bot
b1d4588de1 Automated formatting changes 2020-02-25 19:13:50 +00:00
354d4a321a draft app setup 2020-02-25 20:08:44 +01:00
bcfd1657f8 make methods protected to allow more control from child installers 2020-02-24 22:50:09 +01:00
d9d8f80e72 autoformating 2020-02-24 22:47:27 +01:00
660354d8f4 create settings installer 2020-02-24 22:47:15 +01:00
d32c044b2e Add application info handling 2020-02-24 22:15:24 +01:00
3345d63f20 move file 2020-02-24 22:15:05 +01:00
aa7bb25b36 move ApplicationAbstract 2020-02-24 21:22:35 +01:00
6fc81eeb3f remove keys from foreach 2020-02-22 15:29:25 +01:00
Formatter Bot
6d2b567ba5 Automated formatting changes 2020-02-20 18:39:39 +00:00
37144b9a9f fix writeonly for has many 2020-02-20 19:18:03 +01:00
ea7d504f95 fixes #238 2020-02-20 19:06:50 +01:00
9be83af3c9 fix array typehint 2020-02-20 18:59:49 +01:00
9a0698ae07 fixes #238 2020-02-20 18:55:04 +01:00
6e4981a02e autoformatting 2020-02-20 18:40:02 +01:00
05a1437bca add webserver and webserver tests 2020-02-20 18:39:39 +01:00
01837d3755 add tests 2020-02-19 22:24:58 +01:00
0ff97e74ff auto fixes 2020-02-16 19:55:34 +01:00
4b95814719 add cursor pagination 2020-02-16 19:55:15 +01:00
6d001caaab autoformat fixes 2020-02-15 21:40:44 +01:00
0d48b17866 fix phpstan 2020-02-15 21:40:33 +01:00
e71ef4789d fixes Orange-Management/Orange-Management#48 2020-02-15 18:19:03 +01:00
f19a282f63 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2020-02-15 02:03:24 +01:00
f4ae141981 fixes Orange-Management/Modules#135 2020-02-15 02:00:46 +01:00
135f3f08e4 fixes #162 implemented previously 2020-02-14 18:36:47 +01:00
Formatter Bot
c073ed3c27 Automated formatting changes 2020-02-13 17:56:55 +00:00
7aa99fa987 fix typehints 2020-02-13 18:54:50 +01:00
7835797701 rename http to httpuri 2020-02-12 18:39:47 +01:00
1eda7744f0 use null coalescing assign 2020-02-12 18:13:04 +01:00
Formatter Bot
1f680d89b4 Automated formatting changes 2020-02-11 19:55:36 +00:00
d6d67940a2 rename http classes 2020-02-11 20:47:03 +01:00
652933867d improve basic form element generation 2020-02-10 22:33:42 +01:00
602ce766bb fix typehints 2020-02-09 18:50:05 +01:00
204f3138c9 add json 2020-02-09 15:46:16 +01:00
ae55407219 prepare for better settings 2020-02-08 23:49:31 +01:00
f28515fcf1 fixes #237 2020-02-08 22:31:48 +01:00
Formatter Bot
babbca7fcc Automated formatting changes 2020-02-08 15:51:35 +00:00
86b0d62a54 implement unique 2020-02-08 16:48:07 +01:00
0e0264ad35 improve array docblock 2020-02-08 13:25:48 +01:00
8b2b509c5c implement static localization generation 2020-02-08 12:52:42 +01:00
8710adad62 fixes #234, fixes #189 2020-02-08 12:42:48 +01:00
3e9c16da28 fix typo 2020-02-07 23:45:20 +01:00
56a980d2ea fix bug 2020-02-07 23:33:22 +01:00
f8f85b0092 remove issue todos 2020-02-07 23:20:54 +01:00
426be81077 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2020-02-07 23:14:00 +01:00
0566a34093 fixes #191 2020-02-07 23:12:35 +01:00
71e2d7fc67 fixes #192 2020-02-07 22:34:43 +01:00
d0d77c9b9b fixes #200 2020-02-07 22:02:11 +01:00
3c8a8c31d5 remove todos 2020-02-07 21:51:55 +01:00
b9bc5bbe64 fix #235 2020-02-07 21:41:32 +01:00
Formatter Bot
fb485595a6 Automated formatting changes 2020-02-07 20:07:55 +00:00
166ad5bf4b fix aligns 2020-02-07 21:05:56 +01:00
d20a6b9e8d Implement getBy 2020-02-07 20:37:26 +01:00
4107551a09 fixes #214 2020-02-07 19:20:05 +01:00
3aed840c77 improve baseline 2020-02-06 23:53:39 +01:00
fb968fbef7 fix bugs, phpstan, phpcs 2020-02-06 21:04:34 +01:00
6c917b5486 phpstan/array typehint fixes 2020-02-05 21:09:31 +01:00
8d48e3b317
Improve array docblock NO_CI 2020-02-05 16:56:55 +01:00
2b3a19bbcb
Make array docblock more specific NO_CI 2020-02-05 16:55:48 +01:00
f7ac46d9ab
Improve array docblocks NO_CI 2020-02-05 16:54:16 +01:00
f86a0aa6ed
Make types more specific NO_CI 2020-02-05 16:49:53 +01:00
98adcaad7c
Make types more specific NO_CI 2020-02-05 16:49:07 +01:00
f973d59d58
Improve array docblock NO_CI 2020-02-05 16:42:25 +01:00
ac89a7237c
Improve array docblock NO_CI 2020-02-05 16:40:58 +01:00
1339b43fb7
Improve array docblock NO_CI 2020-02-05 16:39:54 +01:00
24dc0cefdd
Improve array docblock NO_CI 2020-02-05 16:37:09 +01:00
9c21bf4a06
Improve array docblock NO_CI 2020-02-05 16:35:09 +01:00
e0638cb60c
Improve array docblock NO_CI 2020-02-05 16:31:57 +01:00
2b3de00f4c
Don't use use for Throwable NO_CI 2020-02-05 16:28:55 +01:00
0fbbc40237
Improve file cache array docblock NO_CI 2020-02-05 15:54:31 +01:00
067b1856d2
Improve array docblock NO_CI 2020-02-05 15:52:10 +01:00
5e0a6a0fd6
Fix missing docblock components NO_CI 2020-02-05 15:49:51 +01:00
afb31253c8
Update RedisCache.php 2020-02-05 15:48:33 +01:00
dc346a5654
Add more NO_CI 2020-02-05 08:53:26 +01:00
abdb638295
Add NO_CI command 2020-02-05 08:51:14 +01:00
dfba5f1021 start implementing array{} typehint 2020-02-04 21:52:59 +01:00
47cd969f10 add todo and fix docblock 2020-02-04 19:50:41 +01:00
00d9b3eb47 prepare for form element generation 2020-02-04 19:50:20 +01:00
c8a5322e39 undo reset 2020-02-03 20:35:10 +01:00
703c2eb296 optimize localization 2020-02-03 20:30:49 +01:00
a74a7a9aa5 expand datetime construction 2020-02-03 20:30:14 +01:00
c89e773c8e fix type bug 2020-02-03 18:40:47 +01:00
d3e3e90ddd prepare for currency table 2020-02-03 18:34:28 +01:00
a875509703 prepare localization for profile 2020-02-03 17:52:51 +01:00
85b8bbec04 Allow obj relations 2020-02-02 15:49:59 +01:00
3713e3fc11 fixes Orange-Management#202 2020-02-02 15:49:46 +01:00
9a7c3ad0f4 form-data support added 2020-02-01 22:48:00 +01:00
1badf2354b fix samesite bug 2020-02-01 16:30:43 +01:00
f1bbb2abe3 make cookies strict 2020-02-01 15:16:17 +01:00
Formatter Bot
30a8fe202e Automated formatting changes 2020-01-26 13:37:48 +00:00
4b1388bec3 to be fixed 2020-01-26 14:34:59 +01:00
a1ec74e5d9 Remove none-existing code test 2020-01-26 14:33:14 +01:00
004381fdc6
test yaml fix 2020-01-26 14:26:52 +01:00
d41f46ad17 Fix syntax 2020-01-26 14:07:20 +01:00
70bcf1a4c0 Fix syntax 2020-01-26 14:05:25 +01:00
1b6d7ca160 fix action syntax 2020-01-26 13:59:44 +01:00
a60e22d419 test autoformatting 2020-01-26 13:54:48 +01:00
2bf5a69f23 update composer 2020-01-26 13:35:16 +01:00
6ed9992895 expand issue 2020-01-26 13:35:07 +01:00
a18360b5ac fix = alignment 2020-01-26 12:37:55 +01:00
a49251c0bb phpcs fix 2020-01-26 12:27:35 +01:00
65d76e11ea continue graph implementation 2020-01-26 12:06:11 +01:00
89f9d0c2f3 fix self -> static return types 2020-01-26 12:03:12 +01:00
3f132fb60b fix typehint 2020-01-25 22:13:29 +01:00
11bea160b9 fix namespace 2020-01-25 22:13:19 +01:00
5708434b7e added default preloader 2020-01-23 19:20:00 +01:00
28c3d74c31 added preloader 2020-01-23 19:13:04 +01:00
15936c3a1a Add calculation for sample size 2020-01-23 18:49:10 +01:00
59f43a6a87 improve array docblock 2020-01-19 18:54:00 +01:00
caa78ed9d5 started graph implementation 2020-01-19 18:53:52 +01:00
8c0905c39b started graph implementation 2020-01-19 18:53:41 +01:00
5d43137f3c fix todo comments 2020-01-12 17:57:18 +01:00
b58fdb1361 update issue information 2020-01-12 17:54:24 +01:00
13fe7f1061 continue optimizing todos 2020-01-05 21:39:24 +01:00
d8bf78c7b4 fix type hint 2020-01-01 21:31:15 +01:00
a75025c1a0 cleanup todos 2019-12-31 23:36:41 +01:00
4414fad940 add todos from github 2019-12-31 19:54:35 +01:00
41bca90452 fixes #205 2019-12-31 17:12:28 +01:00
777f16f8e5 change workflow key 2019-12-30 18:56:59 +01:00
aaa05e9b1e remove resources from coverage 2019-12-30 18:28:21 +01:00
d442d4f23a Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2019-12-30 18:23:02 +01:00
ed98f5434d
change resource branch 2019-12-30 18:22:49 +01:00
269b33fa7f add workflow 2019-12-30 18:19:29 +01:00
0c04b6ebcd fix resources path 2019-12-30 18:17:35 +01:00
113b00b8e6 fix import 2019-12-30 18:08:01 +01:00
fec9d3750b fix tests excluded 2019-12-30 18:02:54 +01:00
b0727ff8a1 skip tests which depend on modules 2019-12-30 17:55:03 +01:00
e2da707fdf skip tests which depend on modules 2019-12-30 17:42:49 +01:00
8cececccc1 skip tests which depend on modules 2019-12-30 17:37:37 +01:00
ae1cdea043 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2019-12-30 17:29:35 +01:00
f63c69d904 fix xml structure 2019-12-30 17:23:58 +01:00
5b67057ebe
Update main.yml 2019-12-30 14:36:53 +01:00
85b331f51b remove empty pdf wrapper 2019-12-30 14:35:19 +01:00
2346b0606a add docblocks 2019-12-30 14:27:41 +01:00
6bff30df32 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2019-12-30 14:07:04 +01:00
e3b25ce1f4 fix typehint 2019-12-30 14:06:51 +01:00
746db59438 fix typehint 2019-12-30 14:05:58 +01:00
9ed0fed596
Update main.yml 2019-12-30 13:27:57 +01:00
b58e4d86cf
Update main.yml 2019-12-30 13:00:15 +01:00
89935a9fdc fix strict type 2019-12-30 12:43:23 +01:00
4fe59969a9 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2019-12-30 12:24:59 +01:00
52a80f082a updated composer files 2019-12-30 12:24:56 +01:00
71b4881885
Update main.yml 2019-12-30 12:18:21 +01:00
c8830380e5
Update main.yml 2019-12-30 12:12:12 +01:00
39a3a129d6
Update main.yml 2019-12-30 12:08:08 +01:00
cbe1f208c3
Update main.yml 2019-12-30 12:02:57 +01:00
c15836a15d
Create main.yml 2019-12-30 12:00:25 +01:00
3063a6b5a2 cplx still not fully implemented but fixed bug 2019-12-22 11:25:36 +01:00
2a2a655002 remove empty lines from constructor 2019-12-22 11:23:48 +01:00
5e7d806b7f typehint and init value optimization 2019-12-22 11:14:08 +01:00
ca064b75d2 remove stupid initializations and optimize types 2019-12-22 10:37:07 +01:00
aefd1e8cc5 spell checking 2019-12-22 09:37:49 +01:00
6e5f5bb4d3 change session directory permission 2019-12-22 08:25:30 +01:00
bdeca100d5 fix phpcs 2019-12-21 22:10:11 +01:00
792fcf900a fix phpcs 2019-12-21 22:05:53 +01:00
266ae61e53 stricter typehint 2019-12-21 21:41:05 +01:00
db48bcdb8d fix phpstan bugs 2019-12-21 20:51:20 +01:00
34b9ba3097 Add console session draft 2019-12-21 20:51:06 +01:00
f704dfdeff fix typos found due to testing 2019-12-21 16:01:55 +01:00
1262310af9 remove debugging 2019-12-21 15:52:25 +01:00
3dd0c0516d fixes #217 2019-12-21 15:50:03 +01:00
adc31a21b2 the start and end of a day can be created 2019-12-21 12:25:33 +01:00
0f09da42e9 handle uninit dispatcher 2019-12-19 20:11:25 +01:00
e1f10bb82f add possible improvement remarks 2019-12-16 20:44:47 +01:00
3a8a783804 maze render functions generates string 2019-12-15 16:20:11 +01:00
6bb827e97a fix ecb currency parsing 2019-12-15 14:37:44 +01:00
e008c094e5 fix return type 2019-12-15 14:29:50 +01:00
ab385bfbb5 remove empty line 2019-12-15 14:17:43 +01:00
69673a0d36 remove empty lines 2019-12-15 14:11:01 +01:00
acd148b70b add maze generator 2019-12-15 12:45:45 +01:00
7e831763e5 more final and edge case fixes 2019-12-14 21:39:31 +01:00
150f86df4a make final 2019-12-14 21:17:23 +01:00
f29a833016 inspection bug fix 2019-12-12 20:08:53 +01:00
f5e050c0b3 make final 2019-12-10 21:29:52 +01:00
4be0788af8 remove expire remove 2019-12-08 11:57:28 +01:00
1abce14674 fix overwrite bug 2019-12-08 11:48:27 +01:00
da10692f57 debug ttl 2019-12-08 11:47:18 +01:00
5d220b1430 test longer sleep for invalidation 2019-12-08 11:39:31 +01:00
89dd33bd99 try to fix expire bug 2019-12-08 11:31:52 +01:00
25a24c5916 remove special expire functionality 2019-12-08 11:21:47 +01:00
a82f92ea6c fix stat check 2019-12-08 10:39:22 +01:00
c9ae933045 replace delete with del 2019-12-08 10:28:48 +01:00
b1c23eb5e8 replace delete with del 2019-12-08 10:20:03 +01:00
866c78a6b2 fix replace 2019-12-08 10:12:08 +01:00
b3186cce3a debug reverse value for replace 2019-12-08 10:00:37 +01:00
d96798b6b3 handle json serializable 2019-12-08 09:17:13 +01:00
221bc5b2cb add float 2019-12-08 08:48:22 +01:00
0fd5a91a2e fix offset 2019-12-08 08:38:49 +01:00
b0b785bcb0 apparently redis doesn't even have int/float values 2019-12-08 08:32:11 +01:00
14af04f027 maybe fixing type bug 2019-12-08 01:21:30 +01:00
0eb659ce54 fix missing cachify type 2019-12-08 01:07:46 +01:00
be1283d6dc trying to implement acceptable type system 2019-12-08 00:57:54 +01:00
c952489736 adding null support 2019-12-08 00:18:14 +01:00
1a54aefaf7 trying to allow booleans 2019-12-08 00:09:12 +01:00
7c72a40bde fix redis stats 2019-12-07 23:42:57 +01:00
5b61c9718d add allowed datatype 2019-12-07 23:28:04 +01:00
1378cf4b57 add allowed datatype 2019-12-07 23:19:42 +01:00
dbfadd4cc3 fix invalid value set/add 2019-12-07 23:07:35 +01:00
71cc73397d remove many expired tests for memcached which are not supported 2019-12-07 22:47:25 +01:00
886a185c5d memcached stats are seriously broken 2019-12-07 22:35:55 +01:00
a02d251c71 implement false tests because of stupid memcached 2019-12-07 22:26:09 +01:00
3a393e9bda test results are changing somehow 2019-12-07 22:16:53 +01:00
eaf9207610 fix status 2019-12-07 22:08:56 +01:00
8ddf17e42a cleanup data after test 2019-12-07 21:58:52 +01:00
a5b67c20e6 fix setter 2019-12-07 21:48:52 +01:00
c6345da817 don't parse values 2019-12-07 21:37:53 +01:00
4b2d8bc2ed handle invalid keys 2019-12-07 21:28:01 +01:00
6adebce0f8 don't change return type 2019-12-07 21:16:39 +01:00
4e176d7b9e another fix test 2019-12-07 21:06:19 +01:00
4d097b4589 remove threshold 2019-12-07 20:58:23 +01:00
18d457efa6 try to fix caching 2019-12-07 20:50:12 +01:00
70734dfd83 fix test bug 2019-12-07 20:34:52 +01:00
d7ce34a6cc fix phpstan bugs 2019-12-07 19:14:00 +01:00
2350b6cf53 improve tests 2019-12-07 18:38:17 +01:00
7eaf29e912 test documentation and started to enhance explicit coverage which dropped because of @covers 2019-12-07 10:16:54 +01:00
5f632dfca0 fix @covers and comments 2019-12-03 22:27:47 +01:00
48f21805cb add test descriptions 2019-12-03 19:27:46 +01:00
9787e5d2c8 more test cleanups 2019-12-01 19:57:33 +01:00
5e50b896fe tests and cleanup 2019-11-30 19:45:16 +01:00
c2d7d841de split up tests 2019-11-24 14:39:57 +01:00
1a74834831 improve tests 2019-11-24 10:52:03 +01:00
86f77e0a5e cleanup and tests added for ci/cd 2019-11-20 22:27:43 +01:00
0f4739b7b1
Update FileTest.php 2019-11-19 18:06:26 +01:00
76d5d8348b
Update DirectoryTest.php 2019-11-19 18:06:02 +01:00
a7c7025667
Update ImapTest.php 2019-11-19 17:58:25 +01:00
709e9d2d2f
Update Request.php 2019-11-19 17:49:14 +01:00
181467beaf phpstan fixes 2019-11-14 19:10:28 +01:00
d706b8b320 test fixes 2019-11-14 17:45:05 +01:00
7fece66ef6 cleanup tests and add new tests 2019-11-10 22:38:11 +01:00
3e0a4f113f package test and module abstract tests added 2019-11-09 11:55:03 +01:00
f890c78e83 prepare package manager functionality 2019-11-09 10:47:36 +01:00
8a2437051b minor fixes and tests added 2019-11-05 20:28:29 +01:00
e26963c3a8 continue drafting socket 2019-11-03 23:25:34 +01:00
8d4bdc992e create coverage for useless line 2019-11-03 23:25:05 +01:00
165240076a rename connection var 2019-11-03 23:24:45 +01:00
8b3173ed95 cleanup request/response 2019-11-03 23:24:24 +01:00
090b30bb58 cleanup 2019-11-03 23:22:45 +01:00
e952b515d8 fix type hint 2019-11-03 23:22:33 +01:00
8389360eba add test 2019-11-03 23:22:07 +01:00
fd768a208c bug fix spreadsheet IO 2019-11-03 23:21:35 +01:00
5256e40989 add tests and try to fix 0 devision bug 2019-11-03 23:20:53 +01:00
e8e31758c1 change from exception to bool return 2019-11-03 23:20:20 +01:00
16f8566ac3 add invalid credit card test 2019-11-03 23:20:01 +01:00
c65e73d2ac expand options/config functionality 2019-11-03 23:19:38 +01:00
bad1b05de0 optimize, cleanup and add functionality 2019-11-03 23:18:42 +01:00
b50b488fc2 add tests 2019-11-03 23:18:10 +01:00
8995020117 started to cleanup requests/responses 2019-11-03 23:17:46 +01:00
159decf760 implement spreadsheet io test 2019-11-03 23:16:17 +01:00
eb8a0061ce remove travis 2019-10-31 21:21:30 +01:00
f5494f4b31 hopefully fixed devision by 0 2019-10-31 21:16:33 +01:00
18c11fb229 bug fixes and implement some incomplete tests 2019-10-31 21:03:34 +01:00
6c5a7dbdcb Draft client/server socket without functionality 2019-10-28 21:28:38 +01:00
c92f784967 fix namespace of interface 2019-10-28 21:27:40 +01:00
85b828a2bc fix namespace of interface 2019-10-28 21:26:22 +01:00
cfe14cb55b create draft test for socket-server 2019-10-28 21:24:20 +01:00
1e0a49a1b5 rename Router to WebRouter 2019-10-28 21:23:53 +01:00
a6e5b87200 Add dockblock 2019-10-28 21:07:47 +01:00
3ee20e9fc8 Rename Router to WebRouter and implement SocketRouter 2019-10-28 21:07:20 +01:00
6696066f91 fix end of month bug 2019-10-23 13:21:19 +02:00
f0cc8e191e Improved docblocks 2019-10-23 13:20:53 +02:00
2f9834acd5 change root password 2019-10-21 22:20:18 +02:00
baf2218980 Bug fixes 2019-10-21 15:38:15 +02:00
f6fb7f4747 phpcs fixes 2019-10-19 18:50:53 +02:00
a714359ea9 Add comments for test report 2019-10-19 18:11:40 +02:00
f24e6f4681 remove debugging lines 2019-10-19 14:11:31 +02:00
70f1662929 Improve coverage 2019-10-19 13:12:50 +02:00
2e67a95b89 Remove broken and unused code 2019-10-19 13:12:41 +02:00
23fe8d2124 Add try/catch to find hr invalid bytecode escaping 2019-10-19 13:12:12 +02:00
e8ecfce4fd move some functions to array utils 2019-10-19 13:11:27 +02:00
b8ca685473 fix and complete path finding algorithm 2019-10-19 13:10:45 +02:00
0d1b8f5e65 cleanup unused json queries and fix kmeans rng test 2019-10-17 17:09:27 +02:00
a91463d9bd Fix test bugs 2019-10-17 17:03:27 +02:00
549bbfbccf Implement kmeans algorithm 2019-10-17 16:09:03 +02:00
f5208e95fe Implement interfaces for algorithms 2019-10-17 16:08:43 +02:00
7cb47ecea7 Fix construct name 2019-10-17 11:01:19 +02:00
cd352b81a8 prevent initialization 2019-10-17 11:00:51 +02:00
87975e16f1 Implement tests for knapsack and job scheduling 2019-10-17 10:52:19 +02:00
df838d1dee Implemented polynomial regression 2019-10-17 10:51:59 +02:00
002b5a3de5 bug fix classifier - now working 2019-10-17 10:51:24 +02:00
1700f096ae Finalize various interpolation implementations 2019-10-17 10:50:57 +02:00
68f3ecc6f9 Add trivial test case 2019-10-17 10:50:18 +02:00
a504f6bd0e Implement weighted job scheduling 2019-10-17 10:49:52 +02:00
4e3678d498 Finish knapsack implementation 2019-10-17 10:49:33 +02:00
5ee0e67512 make classes final 2019-10-17 10:49:07 +02:00
7c71b023c7 fixes, spline interpolation added 2019-10-16 17:35:10 +02:00
479facee52 Implementd query aliases 2019-10-13 20:38:25 +02:00
b0f452952f uncomment var_dump 2019-10-12 15:29:32 +02:00
577adab857 phpcs fixes and classifier bug fixes/searching 2019-10-12 10:29:26 +02:00
85abb6c520 fix bugs and implement more sort algs 2019-10-11 16:40:09 +02:00
35e410f832 Fix unit test bugs 2019-10-10 22:30:58 +02:00
33ecc44e1f Bug fixes 2019-10-10 20:46:51 +02:00
89c6ba3ac0 continue phpcs fixes 2019-10-10 12:00:54 +02:00
1ecf3e8d8c adding sort and making sure original list is unchanged after sort 2019-10-09 17:45:53 +02:00
b9d0e63beb phpcs fixes + continue distribution implementations 2019-10-09 17:15:12 +02:00
1145144a98 cleanup unused files and phpcs fixes 2019-10-09 01:36:49 +02:00
0422411c89 phpstan fixes 2019-10-07 22:22:41 +02:00
921703a5b5 remove empty construct 2019-10-06 21:00:43 +02:00
e300558db8 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2019-10-06 17:52:31 +02:00
b35b7f1d7a phpcs fixes 2019-10-06 17:41:41 +02:00
1746444975 optimize special case 2019-10-05 20:49:41 +02:00
8e292966c9 Fix uri shortening for query para duplication 2019-10-05 20:45:00 +02:00
1e0a841447 Add docblocks 2019-10-05 20:01:08 +02:00
85746809af continue drafting l11n default files 2019-10-05 20:00:47 +02:00
e34e30f776 fix loop counter style 2019-10-05 20:00:18 +02:00
0f11df6f95 Change encoding to real utf8 2019-10-05 19:59:53 +02:00
ac0503c6e9 phpstan fixes 2019-09-29 01:12:58 +02:00
8221d4b723 phpcs fixes 2019-09-29 00:11:20 +02:00
cd58375f02 fix mapper formats 2019-09-28 23:11:50 +02:00
9511d3209c fix empty lines 2019-09-28 20:58:36 +02:00
59124f1d1f
Update README.md 2019-09-28 20:25:59 +02:00
a51be51c03 fix docblock 2019-09-21 16:12:30 +02:00
559ebf200d fix docblock 2019-09-21 15:26:53 +02:00
6336898978 fix phpcs findings 2019-09-12 19:46:27 +02:00
af294ff9ac Fix minimum coins for value test 2019-09-09 20:14:47 +02:00
26383f1cde test fixes 2019-09-09 19:51:35 +02:00
c41a59ad1d try to improve performance 2019-09-07 08:45:24 +02:00
27035d8be7 prepare for more algorithms 2019-09-06 21:25:09 +02:00
2c4155b674 streamline heuristic by using metrics implementation 2019-09-04 21:39:29 +02:00
c9e439c0f4 Fix bugs/typos 2019-09-04 20:39:29 +02:00
bebfbafae8 added metrics. @todo: implement n-dim 2019-09-04 20:39:11 +02:00
96b9d4d1a5 fix ; typo 2019-09-03 21:29:06 +02:00
e12ad5212d Merge localization datamapper support (not finished yet) 2019-09-03 21:01:31 +02:00
20791b6efe fix invalid comp. function 2019-09-03 20:57:02 +02:00
675c4bcd3c fix cpu % 2019-09-03 20:56:31 +02:00
e0aa1406e2 Add heap 2019-09-03 20:56:05 +02:00
743ba4a937
Implement missing conditional functionality (delete, update) 2019-09-03 15:38:09 +02:00
bb1aa4044a
Draft conditional data 2019-09-03 14:49:42 +02:00
34cc6325da fix type hinting 2019-08-25 21:45:02 +02:00
0acef08f09 implement int shift 2019-08-25 21:44:42 +02:00
1b2705291d start implementing heap 2019-08-25 21:44:11 +02:00
a85d205cf3 start implementing pathfinding 2019-08-25 21:43:43 +02:00
b38ebb92c0 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2019-08-20 19:22:32 +02:00
c8ec18f912
Create Path.php 2019-08-20 17:34:47 +02:00
ce0a98c7a8
Update PathFinderInterface.php 2019-08-20 17:31:08 +02:00
309b661fab
Create PathFinderInterface.php 2019-08-20 17:21:24 +02:00
6efc4e157b
Update Grid.php 2019-08-20 16:36:14 +02:00
095fd15607
Update Grid.php 2019-08-20 16:28:38 +02:00
aec62e3eb2
Update Node.php 2019-08-20 16:20:38 +02:00
ea85dd5f25
Update Grid.php 2019-08-20 16:13:05 +02:00
8f3eeac987
Update Node.php 2019-08-20 16:10:39 +02:00
cdbfa4e1b0
Update Node.php 2019-08-20 16:10:20 +02:00
5aad7af88f
Update Node.php 2019-08-20 16:08:31 +02:00
2fdb32d1d6
Update MovementType.php 2019-08-20 16:03:41 +02:00
463ff29c19
Update MovementType.php 2019-08-20 16:02:46 +02:00
abfc337978
Update HeuristicType.php 2019-08-20 16:00:34 +02:00
b604abfdae
Update HeuristicType.php 2019-08-20 15:59:56 +02:00
a3abbbb9e1
Create Dijkstra.php 2019-08-20 15:27:54 +02:00
f12d1834aa
Create BestFirstSearch.php 2019-08-20 15:27:37 +02:00
3e2805b140
Rename JPS.php to JumpPointSearch.php 2019-08-20 15:27:22 +02:00
5c2ca9cc83
Create BreadthFirstSearch.php 2019-08-20 15:27:01 +02:00
324ab2d21f
Create IDAStar.php 2019-08-20 15:26:37 +02:00
5eb3881b28
Create AStar.php 2019-08-20 15:25:49 +02:00
87a5577721
Create MovementType.php 2019-08-20 15:24:29 +02:00
8c9c5c192e
Create JPS.php 2019-08-20 15:23:11 +02:00
071c6a010e
Create HeuristicType.php 2019-08-20 15:23:00 +02:00
0878f9498d
Create Node.php 2019-08-20 15:22:26 +02:00
2059f85800
Create Grid.php 2019-08-20 15:22:17 +02:00
3bb09081d4
Create Heuristic.php 2019-08-20 15:22:06 +02:00
047d8c3028 Implement more sorting algorithms 2019-08-17 22:33:09 +02:00
7b1cf0e660 fix after change to php 7.4 2019-08-17 14:14:58 +02:00
dd68825329 Bug fix type hint 2019-08-15 22:19:45 +02:00
5341d2a6b8 implement php 7.4 type hints 2019-08-15 22:02:01 +02:00
b4084913de Implement php 7.4 type hints 2019-08-15 21:54:59 +02:00
eb7dbe4663 start implementing php 7.4 2019-08-15 20:44:04 +02:00
9d6ecedba2 autofixes 2019-08-10 23:23:06 +02:00
64198f0562 start impl. sort algorithms 2019-08-10 23:21:26 +02:00
2d64308b78 assert null 2019-08-10 23:17:12 +02:00
0ca13206fe fix datetime value bug 2019-08-10 23:16:27 +02:00
5d8577725a add file types 2019-07-30 20:26:04 +02:00
c10708ee23 fix @link 2019-07-08 19:51:19 +02:00
5b56b7367d fix formatting and docblock 2019-07-08 19:15:25 +02:00
08bf6984cd Add cache ignore 2019-07-04 22:36:34 +02:00
a9918edccf Add exception description 2019-07-04 22:35:41 +02:00
7a88ce1576 php cs fixes 2019-06-15 19:14:20 +02:00
8a21347547 fix , in function 2019-06-14 23:43:42 +02:00
4da69b5c09 fix code and tests after changes 2019-06-14 23:08:09 +02:00
2be8f427c9 Implement missing tests 2019-06-09 22:15:48 +02:00
719996dc07 load locale with invalid country code 2019-06-09 21:42:43 +02:00
cb4c6a4a2e Improve tests and add missing reverse calculation 2019-06-09 21:34:24 +02:00
ab58467fc0 sanitize option keys 2019-06-07 22:57:37 +02:00
7572fc2d90 automatically define path indices 2019-06-07 21:18:29 +02:00
da72383619 fix docblock and function parameter 2019-06-07 20:54:52 +02:00
93a972eb55 static analysis fixes 2019-06-06 21:43:45 +02:00
44a003b787 improve csrf check 2019-06-05 22:24:55 +02:00
7ad7e9be41 fix formatting 2019-06-05 22:23:13 +02:00
47ebeba041 remove implemented todos 2019-06-05 22:22:36 +02:00
3d39929180 More general routing and hidden server responses 2019-06-01 20:55:46 +02:00
31812f701c Re-evaluate base after root path change 2019-05-27 21:56:21 +02:00
8f0688f46d Fix depth bug 2019-05-25 11:16:10 +02:00
a62304baaa Fix extension type test 2019-05-25 11:15:47 +02:00
1f840c7c04 Added collection type handling 2019-05-22 07:47:23 +02:00
4633c209a6 Fix bug. now post data overwrites uri parameter. before it was the other way around. 2019-05-19 14:20:37 +02:00
5965f2a4ca bug fixes and better response handling 2019-05-07 20:00:30 +02:00
7eb8322d71 Fix typehint 2019-05-01 20:59:26 +02:00
b6f5e801a8 Implement rest getJson 2019-05-01 20:56:29 +02:00
45b22c780a Use Response as response 2019-05-01 20:38:49 +02:00
7cce8ca1a6 Improve sharding (not finished) 2019-04-28 21:15:04 +02:00
b250f24880 Add testdox 2019-04-28 21:14:46 +02:00
6f2dd4d30a draft update file 2019-04-27 18:29:56 +02:00
ff91b98a44 Improve robustness 2019-04-27 12:05:06 +02:00
bc77b62685 Fix whitespace 2019-04-27 10:49:43 +02:00
872b613d87 strict types 2019-04-27 10:41:17 +02:00
c799124d12 php cs fixes 2019-04-27 10:34:00 +02:00
4cdfab275e Use global namespace 2019-04-27 00:13:34 +02:00
665a9d4655 Add option for stringify (json_encod now) 2019-04-22 16:31:50 +02:00
35d47c7a53 Add getter 2019-04-22 16:31:20 +02:00
39103b5ec6 Add file types 2019-04-22 16:30:48 +02:00
1a2e49c605 Improve tests 2019-04-19 22:49:14 +02:00
135b7bf30d Improve tests and harmonize permission handling 2019-04-19 20:49:46 +02:00
99f429f7ed Improve account test 2019-04-19 19:01:59 +02:00
492430ea8a Split up tests 2019-04-18 22:56:08 +02:00
65b9c41dbf Remove empty lines 2019-04-15 20:05:41 +02:00
2d45eb8fa1 Remove . 2019-04-15 20:02:59 +02:00
f73d7f0d39 Spelling fix 2019-04-15 20:02:12 +02:00
0245fcf317 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2019-04-15 20:00:49 +02:00
af77f42eeb Draft @testdox example 2019-04-15 20:00:28 +02:00
0267086a32
Update README.md 2019-04-15 18:37:05 +02:00
b86c63460b
Update README.md 2019-04-15 18:18:00 +02:00
31e41cd949
Update README.md 2019-04-15 17:51:30 +02:00
49cb38ff4f ignore uncoverable lines 2019-04-14 21:14:33 +02:00
be9636a846 fix #196 #197 2019-04-14 19:46:32 +02:00
26a13b1276 fixes #197 2019-04-14 18:57:11 +02:00
34c2673504 Fix missing column 2019-04-14 18:38:07 +02:00
743e182949 Add todo 2019-04-12 23:16:22 +02:00
eac63202f7 Fix csrf check and unit tests 2019-04-12 23:12:47 +02:00
95869f70c4 Reduce match overhead 2019-04-12 22:55:09 +02:00
35360ef7a8 Add optional csrf check in routing 2019-04-12 22:37:18 +02:00
c01846ca1f Update Readme 2019-04-09 22:47:06 +02:00
2596659125 More unit tests 2019-04-09 19:51:07 +02:00
1c4dd55396 Allow attributes 2019-04-01 21:54:26 +02:00
905d04957d Fixes 2019-03-31 20:05:49 +02:00
b286fa4de1 Fix routing 2019-03-17 19:32:27 +01:00
b62d213000 Fix invalid ftp login 2019-03-17 18:21:57 +01:00
e8bed84e6e Fix abstraction 2019-03-17 17:53:57 +01:00
c59c2d9f2a Fix app name recognition bug 2019-03-17 16:42:06 +01:00
38ed968cc5 Add path offset 2019-03-17 16:39:54 +01:00
8203389ec0 fix lang in console 2019-03-17 14:34:51 +01:00
20d18c8ba8 Fix data check 2019-03-17 13:57:33 +01:00
4bd64e4b36 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2019-03-17 13:10:26 +01:00
ad4a2c42a5 Fix phpunit 8 tests 2019-03-17 12:22:55 +01:00
a61a62adcc Use equalsWithDelta 2019-03-17 11:38:01 +01:00
c316c1715a Remove annotation 2019-03-17 11:16:15 +01:00
69ee452af7 Fix build 2019-03-16 23:30:57 +01:00
a52d01da80 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2019-03-14 18:51:08 +01:00
87ed2174d8 add port to base path 2019-03-14 18:51:05 +01:00
632322fa88 Fix bugs 2019-03-09 23:18:21 +01:00
b9a82ea08d Improve localization 2019-03-09 21:42:21 +01:00
89c14a69b8 Add better uri creation from current 2019-03-09 19:33:25 +01:00
632ce1c4dc Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2019-03-09 18:53:39 +01:00
bfa360ce24 Get subdomain 2019-03-09 18:53:33 +01:00
bddeff5a0c Fix base scheme 2019-03-09 16:28:09 +01:00
80f58b9d24 Fix base scheme 2019-03-09 16:26:18 +01:00
156c5849c7 Fix current uri scheme 2019-03-09 16:16:07 +01:00
1e79d9616a Set port 2019-03-08 20:53:43 +01:00
97cf8dd5a8 Make app optional 2019-03-07 19:00:15 +01:00
d33f24aa6b Fix matrix bugs 2019-03-03 22:03:59 +01:00
169d361522 test and fix schema builder 2019-02-26 21:42:17 +01:00
0bd6cb95f5 test and fix schema builder 2019-02-26 21:41:52 +01:00
6e2bfebc60 Fix json template validation bugs 2019-02-25 23:56:58 +01:00
e60952e75b Allow to return null module 2019-02-20 22:47:21 +01:00
ed34d8d454 fix comments 2019-02-17 21:36:14 +01:00
fd3778cde1 Create oauth2 placeholder 2019-02-16 01:29:02 +01:00
187999ccfc Fix test after path changes 2019-02-15 19:45:32 +01:00
ea8a63b952 Bug fix and docblock 2019-02-14 23:41:55 +01:00
1f5e18985f Fix string diff markup 2019-02-14 19:27:49 +01:00
10fd3ee7da add missing diff function 2019-02-14 18:53:24 +01:00
5db3d81d25 Make count( use global namespace 2019-02-11 22:25:57 +01:00
ebad6f044f fix incrementer from post to pre 2019-02-11 17:27:04 +01:00
9661171851 Add diff function for str. changes 2019-02-11 17:26:17 +01:00
8d15c645a9 Fix absolute path to relative paths 2019-02-11 11:39:11 +01:00
98d969fece implement ftp 2019-02-09 19:43:30 +01:00
48f2552311 phpcs+phpstan fixes 2019-02-07 00:05:38 +01:00
0d55e17842 Use global namespace+minor fixes 2019-02-04 22:30:05 +01:00
60685547b6 Add downloadable+array query data 2019-02-02 23:56:43 +01:00
c111b2d432 Fix root namespace 2019-02-01 22:20:32 +01:00
c959e5e5de Fix self/static bug 2019-01-20 12:03:10 +01:00
d3cfe29e14 Add new status 2019-01-13 21:40:06 +01:00
e0003be06b replace TBD package with tests 2019-01-11 21:15:53 +01:00
473f762bd9 change to include 2018-12-30 20:42:41 +01:00
54409c9f12 bug fixes 2018-12-30 20:16:27 +01:00
b04628f890 minor performance improvements 2018-12-30 19:49:55 +01:00
29bee2e1f5 Improve docblocks 2018-12-28 23:08:24 +01:00
7af3cb042f Fix increment 2018-12-28 19:23:48 +01:00
a80224b07d php cs fixer 2018-12-28 19:13:07 +01:00
9a09993336 Fix use order/unused 2018-12-28 18:42:14 +01:00
8815028589 Improve documentation 2018-12-25 20:09:11 +01:00
15d2b5f7dd Implement more unit tests 2018-12-25 16:17:19 +01:00
336495db02 Fix reInit call 2018-12-23 20:31:58 +01:00
c0ded5607c Allow creation of models with id 2018-12-23 17:32:18 +01:00
42d5d274b2 Implement cache tests and stringify tests 2018-12-23 10:58:53 +01:00
10f0d1f692 Fix whitespace 2018-12-22 19:54:18 +01:00
2f38afaef7 Prepare for json schema installation 2018-12-22 19:50:51 +01:00
835f9a5f64 Prepare for json schema installation 2018-12-22 19:50:10 +01:00
4fc518dd4b Prepare for automatic table create 2018-12-21 20:21:50 +01:00
d4ec08179e Implrement create builder 2018-12-21 20:16:33 +01:00
6cc59da699 Add json template validation 2018-12-20 23:22:44 +01:00
4ed4caf55b Fix bugs 2018-12-16 11:22:27 +01:00
857970c230 Fix docblocks 2018-12-15 22:35:41 +01:00
e616f844ab Use self instead of class 2018-12-10 18:24:46 +01:00
4b955eeb63 Fix decrement order 2018-12-10 18:20:39 +01:00
2f32c9e22b Fix increment order 2018-12-10 18:18:34 +01:00
13c5562ffe Fix null typehint order 2018-12-10 18:13:44 +01:00
e01d3e1e59 Fix doc align 2018-12-09 22:20:41 +01:00
f9bf85e702 Fix use order 2018-12-09 22:16:41 +01:00
015fd41ba5 Remove unused use 2018-12-09 22:02:15 +01:00
07776f489c Fix pullout bugs 2018-12-09 18:01:20 +01:00
296eb7c20b Remove whitespace 2018-12-09 16:30:43 +01:00
c125937f05 Simplify output 2018-12-09 16:24:24 +01:00
79ddd42321 Add stringify 2018-12-09 16:24:01 +01:00
9aaf6e0125 Add general api actions update,create,delete 2018-12-09 16:22:14 +01:00
b8f375480d Fix docblocks 2018-12-08 21:49:02 +01:00
92374d311f inspection fixes 2018-12-08 14:25:43 +01:00
4bd0a0f1b3 Fix event bug 2018-12-02 16:45:22 +01:00
c126670789 Implement file import 2018-12-01 22:27:10 +01:00
d4bc7a66bf optimize file import 2018-12-01 22:26:25 +01:00
7a7505193d Allow array multiple callbacks per trigger 2018-12-01 21:42:22 +01:00
51894cbbb5 Fix formatting 2018-12-01 20:46:41 +01:00
7f603656f3 Add regex group trigger support 2018-12-01 20:44:00 +01:00
d47f3aa19d Fix lock(). make member 2018-11-30 22:06:03 +01:00
ce939eb7de Force logging output 2018-11-30 21:06:12 +01:00
606069056e Fix spaces 2018-11-23 11:47:55 +01:00
9945dbc373 Bug fixes 2018-11-23 11:35:42 +01:00
8c3392253f Test and impl. fixes 2018-11-18 12:49:59 +01:00
19019936bc Draft schema builder 2018-11-11 19:53:54 +01:00
65e35ec38e fix backslash bug 2018-10-27 20:41:39 +02:00
6e6ce55bb8 fix tar source path 2018-10-20 18:45:31 +02:00
d708546c27 Fix path 2018-10-20 18:40:57 +02:00
823f161451 Fix temp file name 2018-10-20 18:37:38 +02:00
dc53adec3c fix overwrites 2018-10-20 18:24:03 +02:00
04704e67cf change file permission 2018-10-20 18:12:22 +02:00
e7b72e519a fix test 2018-10-20 18:08:32 +02:00
d21533a446 fix path 2018-10-20 18:01:17 +02:00
4f081aaa71 implement tests 2018-10-20 17:57:48 +02:00
0be02d40c2 fix package test + graph test started 2018-10-15 19:20:07 +02:00
d7a86d3a49 Test for empty delete 2018-10-14 22:28:55 +02:00
499cf41db2 Fix testing bugs 2018-10-14 22:28:21 +02:00
de7ef32dbb Start packagemanager tests 2018-10-14 22:00:53 +02:00
e8e036173d Allow simple array ontop of key=>value 2018-10-14 21:59:57 +02:00
2023b9ab75 75% code coverage 2018-10-14 13:03:13 +02:00
64c9cda54e Remove sqlite database after test 2018-10-10 23:38:22 +02:00
b979761e8c More tests, test conditions and number_format fixes 2018-10-10 23:32:28 +02:00
156879f161
Update PostgresConnectionTest.php 2018-10-10 15:12:06 +02:00
4facb82bb3 Test fixes 2018-10-07 20:26:51 +02:00
b0c58616ff Prepare evd 2018-10-07 14:33:15 +02:00
cd875f52cd More distribution tests 2018-10-06 21:47:45 +02:00
c491d2a4ff Split factory tests 2018-10-06 16:00:13 +02:00
dc65cfdb02 Remove cache install 2018-10-06 15:54:03 +02:00
795e0f29d6 Add more unit tests 2018-10-06 15:50:27 +02:00
246001a1f2 Last travis test for today 2018-10-05 22:39:16 +02:00
c46a2725c2 Next travis install test 2018-10-05 22:28:49 +02:00
bb356cd7b0 Install libmemcached 2018-10-05 21:48:35 +02:00
4c038c3f26 Remove memcached install 2018-10-05 21:36:51 +02:00
5c85b21b1d Install libmemcached 2018-10-05 21:31:42 +02:00
084a5a4b19 pecl use default settings 2018-10-05 21:23:08 +02:00
7c50ec748f travis test continues 2018-10-05 21:18:04 +02:00
5c1b449593 travis test continues 2018-10-05 21:14:00 +02:00
c1083a1a33 travis test continues 2018-10-05 21:09:24 +02:00
ab842f5703 redis already installed 2018-10-05 21:04:19 +02:00
0a6e6beaef Test new travis cache install 2018-10-05 20:59:42 +02:00
9eecd70088 Implement cache and unit tests for cache 2018-10-05 20:49:02 +02:00
527d6521ac Add more rng tests 2018-10-03 16:38:47 +02:00
52d8b17914 Bug fixes and unit tests implemented 2018-10-03 14:25:26 +02:00
427c97bfb3 Set tests packages to tests 2018-10-02 22:15:50 +02:00
a8f7b0c375 Add more unit tests 2018-10-02 22:11:31 +02:00
847c8d2a42 Move models to framework 2018-10-02 21:23:06 +02:00
6766ed562a Remove empty line 2018-09-29 08:10:41 +02:00
e9f1adc699 docblock lie to fix some phpstan bugs 2018-09-22 19:09:12 +02:00
dad9a42ece Docblock fix 2018-09-22 18:19:04 +02:00
a348bda2da Fix indention of = 2018-09-22 14:00:04 +02:00
69d94e8181 Fix phpstan 2018-09-22 13:46:59 +02:00
4e68ca4bae Fix phpstan 2018-09-22 13:25:00 +02:00
10f392408c Fix return type hint 2018-09-22 13:17:50 +02:00
dad943059f Remove type cast 2018-09-22 13:04:59 +02:00
3fbb441d13 Phpstan fixes 2018-09-22 12:41:14 +02:00
8a91224f66 Fix whitespaces 2018-09-21 23:17:37 +02:00
536d480a36 Fix permission type and error logs 2018-09-21 23:01:49 +02:00
bfc457115c Split controllers per application 2018-09-19 21:33:10 +02:00
430be41982 Move ownership from modules to framework 2018-09-17 19:38:00 +02:00
f8bad0558b Move ownership from modules to framework 2018-09-17 19:36:38 +02:00
3e2c676530 Fix edge cases for request types 2018-09-15 17:12:19 +02:00
2a01540348 Fix edge cases for request types 2018-09-15 17:11:33 +02:00
362631a6ec Add getter for json and list data 2018-09-15 14:35:00 +02:00
a4f0d7c13b Add getter for json and list data 2018-09-15 14:34:37 +02:00
aaf7c71628 Add getter for json and list data 2018-09-15 14:33:06 +02:00
378a569316 Add getter for json and list data 2018-09-15 14:32:37 +02:00
23f31d359a Prevent creating existing object in database 2018-09-15 14:18:58 +02:00
4e66128ea4 Extend functionality based on module needs 2018-09-15 13:30:51 +02:00
84d64ed53f Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2018-09-12 22:19:28 +02:00
a95b0ea026 PhpStan fixes 2018-09-12 22:15:44 +02:00
5bfba4b202 Extend permutation test for other return 2018-09-12 21:36:19 +02:00
efb6421289 Add docblocks for phpstan tests 2018-09-12 21:32:59 +02:00
65e0a5d024
Update Graph.php 2018-09-12 09:19:16 +02:00
1bf1e6da3b Fix para types 2018-09-11 21:19:55 +02:00
4b791bf12d Implement queue 2018-09-09 23:35:35 +02:00
105d4f355b Fix multimap implementation and add tests 2018-09-09 20:06:18 +02:00
5b3178e049 Fix validation bug 2018-09-08 19:40:19 +02:00
5dd679698b Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2018-09-08 19:07:42 +02:00
dbe837a52e Bug fixes from tests 2018-09-08 19:06:42 +02:00
39635c1115 Remove todos and make use of query builder 2018-09-08 18:22:34 +02:00
ac1749a9bb
Index bug fix 2018-09-05 19:26:53 +02:00
180bb9c6b9
fixes #181 2018-09-05 16:24:10 +02:00
7a5f75eedc fixes #178 2018-09-04 22:27:05 +02:00
1ae4bba960 fix #180 2018-09-04 21:22:33 +02:00
0e8876ce4d More unit tests 2018-09-02 21:26:00 +02:00
766b79cfd3 Remove unused function 2018-09-01 17:50:10 +02:00
acb32ba190 Implement more array functionality 2018-09-01 17:23:34 +02:00
f1326f4a75 Improve tests 2018-09-01 16:28:00 +02:00
a748d50b0a improve unit tests 2018-08-31 21:15:11 +02:00
a260c776cc optimize coverage report 2018-08-31 17:36:01 +02:00
10494cc160 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2018-08-29 16:35:20 +02:00
c7ee1fadab Make app optional for init 2018-08-29 16:34:52 +02:00
39b6f656f6
Undo creating new sub arrays as this seems to be not required 2018-08-28 20:21:17 +02:00
a37dd5e792
Create array if not existing 2018-08-28 20:17:22 +02:00
a022348e47
Fix namespace 2018-08-28 20:13:46 +02:00
70610fbd70
Remove unused reference 2018-08-28 19:50:07 +02:00
8716d80efb Fix namespace bug 2018-08-27 11:09:56 +02:00
cf161359c2 remove comment 2018-08-26 19:25:23 +02:00
fa5bf4fe24 Add additional enum to tests 2018-08-25 20:19:05 +02:00
17740d864f Implement join for builder 2018-08-25 18:37:08 +02:00
11c78afbbe Fix invalid global namespace 2018-08-24 21:09:40 +02:00
e28353a86b More global namespace uses 2018-08-24 15:01:01 +02:00
138b631a65 Use more global paths 2018-08-24 14:48:49 +02:00
d5e2d35672 Fix package docblock 2018-08-24 14:08:19 +02:00
9ad6be02bf comment fixes 2018-08-24 14:06:05 +02:00
8a2bed5877 use global namespace 2018-08-24 13:06:04 +02:00
feb652a026 Merge remote-tracking branch 'origin/develop' into develop 2018-08-24 12:09:50 +02:00
7cb13c09e7 Use more global namespace 2018-08-22 21:01:57 +02:00
de2fdb61bc Handle empty table name in where clause 2018-08-18 12:41:53 +02:00
1caf381603 Load localization based on language or locale 2018-08-18 09:21:52 +02:00
df2bd5b624 Fix type bug 2018-08-17 20:00:34 +02:00
cd8f4945e6 Implement permission check in routes 2018-08-17 19:56:21 +02:00
8a3893b36b Add build status 2018-08-12 11:17:24 +02:00
4994050839 Exclude vendor 2018-08-12 10:52:58 +02:00
df8d6c42c0 Exclude vendor 2018-08-12 10:43:33 +02:00
1017a3a003 Fix coverage path 2018-08-12 10:26:57 +02:00
bd935810bf Add code coverage 2018-08-12 10:12:46 +02:00
d89ba9832a Test invalid php syntax 2018-08-11 16:42:11 +02:00
2b49245901 Test invalid php syntax 2018-08-11 16:36:36 +02:00
f5ec5b320d Test invalid php syntax 2018-08-11 16:30:04 +02:00
b2037ddf92 Test invalid php syntax 2018-08-11 16:13:17 +02:00
ce469cbae3 Disable test for travis 2018-08-11 15:25:17 +02:00
ac3711768c Test path guessing 2018-08-11 15:11:46 +02:00
94eb099fb9 Check correct cron/schedule path 2018-08-11 15:10:05 +02:00
9085fa7a7e Fix separate phpOMS tests without other components 2018-08-11 15:01:01 +02:00
2b29a3c012 Fix catching throwables 2018-08-11 14:51:53 +02:00
356027981f Use local phpunit 2018-08-11 14:20:21 +02:00
bd87ffadff More build fix tests 2018-08-11 13:51:41 +02:00
71022d13b1 Fix some travis build bugs 2018-08-11 13:28:55 +02:00
108ad59bd9 Fix some travis build bugs 2018-08-11 13:16:29 +02:00
828ee4f2ed Get current path 2018-08-11 12:51:05 +02:00
d8494e439c Try to fix unittests for travis 2018-08-11 12:46:36 +02:00
891b94a889 Make build hooks executable 2018-08-11 12:31:11 +02:00
0b6adc9244 Make build hooks executable 2018-08-11 12:31:08 +02:00
08d5987553 Use global namespace 2018-08-11 12:10:36 +02:00
e5c70b1b43 Extend build script 2018-08-11 12:10:21 +02:00
24659e324f fixes #158 2018-08-09 18:43:03 +02:00
175be313d2 Remove pw 2018-08-04 20:23:35 +02:00
a4f8b114bb Cleanup minor visual bugs 2018-08-04 20:22:33 +02:00
165f748850 fixes #25 2018-08-04 18:54:42 +02:00
55b2d30837 Exclude vendor 2018-08-04 16:55:56 +02:00
e39ad5a2f9 Exclude vendor 2018-08-04 16:54:16 +02:00
e6be0fe09f Exclude vendor 2018-08-04 16:49:06 +02:00
aed9ec74a5 Fix test files 2018-08-04 16:43:49 +02:00
ca7d6f8b54 Use default phpunit 2018-08-04 16:38:40 +02:00
f03399369d Remove phan 2018-08-04 16:28:45 +02:00
fdb5c9818d Remove phan 2018-08-04 16:28:33 +02:00
2ea3b16828 Remove db password 2018-08-04 16:24:51 +02:00
eb222ae98a Remove container etc 2018-08-04 16:22:51 +02:00
2f01932b43 Use older mysql 2018-08-04 16:20:48 +02:00
7b799ee7d8 Try to restart mysql 2018-08-04 16:19:57 +02:00
75c3ca9ffc Try to restart mysql 2018-08-04 16:16:10 +02:00
5a71144588 Try to restart mysql 2018-08-04 16:10:40 +02:00
5001003414 Fix change password command 2018-08-04 16:07:38 +02:00
0407659445 use different password change 2018-08-04 16:05:44 +02:00
886cc8b6bf Check without mysql restart 2018-08-04 16:01:29 +02:00
9fa2d7067a Use sudo 2018-08-04 16:00:13 +02:00
06757d9a83 try sudo 2018-08-04 15:59:28 +02:00
1783ef3804 Use old db version 2018-08-04 15:57:11 +02:00
4f968d4420 Test db variation 2018-08-04 15:55:01 +02:00
73192e179a Remove sudo 2018-08-04 15:51:56 +02:00
26b6a605ad Test sudo 2018-08-04 15:51:15 +02:00
c44b9f0949 Use sudo 2018-08-04 15:48:32 +02:00
3dbd887702 Fix mysql database 2018-08-04 15:39:39 +02:00
cbac440141 Fix vendor path 2018-08-04 15:34:49 +02:00
16bddd7866 Fix vendor path 2018-08-04 15:32:21 +02:00
a8e32cadff Fix config path 2018-08-04 15:25:42 +02:00
e45895b850 Fix composer structure 2018-08-04 15:12:57 +02:00
3e9d5f4108 install ast 2018-08-04 15:09:38 +02:00
121fb83695 Test travis build 2018-08-04 15:04:01 +02:00
d4ed7b0e19 Fix invalid stripos 2018-08-04 13:43:59 +02:00
d7337e9e1b Fix schedule/cron implementation 2018-08-04 13:20:57 +02:00
a33a7be954 fixes #26 2018-08-02 19:18:34 +02:00
ed3fc48e34 fixes #26 2018-08-02 18:45:36 +02:00
e61c1fb5dd fixes #26 2018-08-02 18:30:24 +02:00
16e0462a89 fixes #26 2018-08-02 18:30:20 +02:00
6cc520a579 Fix mapper depth bugs and implement math evaluator 2018-08-01 22:08:20 +02:00
cdfb8894b9 Add encoding change function 2018-08-01 19:42:00 +02:00
1e023a1247 Fix depth handling 2018-07-31 20:10:20 +02:00
57da54ad44 Fix download and code inspection bugs 2018-07-31 18:24:49 +02:00
6a14f221ee Add abstract function 2018-07-29 21:53:21 +02:00
47dfb029f7 Fix indention 2018-07-29 21:37:09 +02:00
8f3c90718f Use global namespace 2018-07-29 21:35:51 +02:00
2b81ab274b Fix bad log lines 2018-07-29 21:30:37 +02:00
dbdce97904 Make binary path private 2018-07-29 21:17:12 +02:00
8a3b9ee2f8 Use root namespace and impl. guess bin path 2018-07-29 21:16:13 +02:00
9a220a85a7 Use global namespace 2018-07-28 20:46:39 +02:00
ee018f124f Prevent exception of arrays 2018-07-28 20:46:28 +02:00
244e2e8d86 Allow empty email 2018-07-28 20:45:46 +02:00
999b60999f Fix pre minification bug 2018-07-28 13:39:44 +02:00
416f350fdb Hint orgId for public reads 2018-07-27 20:11:43 +02:00
d81ff1dc7a Fix factory return type 2018-07-27 20:05:18 +02:00
0877aeb7d5 Implement console framework features 2018-07-27 19:52:56 +02:00
b7d3427e62 Use global namespace 2018-07-24 20:18:34 +02:00
d75e12b67b console app draft 2018-07-24 19:30:21 +02:00
eebace5030 console app draft 2018-07-24 19:30:15 +02:00
b82213d97f Turn some returns into exceptions 2018-07-18 00:12:53 +02:00
46465207a7 Fix types 2018-07-18 00:05:00 +02:00
72d2e3ad77 Fix types 2018-07-17 22:26:25 +02:00
a0b51cef62 Fix types 2018-07-17 21:38:32 +02:00
d633d96462 Type fixes 2018-07-17 18:49:46 +02:00
c688f12c06 Better type juggling 2018-07-15 21:50:10 +02:00
dbd216aa3b Better type juggling 2018-07-15 21:48:56 +02:00
b6782198c0 Fix types 2018-07-15 21:41:30 +02:00
a3fd37fd84 Fix types 2018-07-15 21:22:25 +02:00
1200350c62 Minor type fixes 2018-07-15 20:10:53 +02:00
2d20d913e3 Fix empty line 2018-07-15 11:49:09 +02:00
6843ac5548 Type check fixes 2018-07-15 10:46:34 +02:00
da9b2d3406 Fix mini bugs 2018-07-15 00:04:08 +02:00
23eb9ab80a More type fixes 2018-07-14 23:41:51 +02:00
adf83f0867 Fix path 2018-07-14 23:06:58 +02:00
67490f42e6 More type fixes 2018-07-14 22:58:44 +02:00
2fdc68e7e6 More static test fixes 2018-07-14 22:36:41 +02:00
0069bdac9a Static test fixes 2018-07-14 22:19:48 +02:00
d1fafd760b More type checks 2018-07-14 20:11:34 +02:00
42877f570d More type checks 2018-07-14 20:11:31 +02:00
c8d938591a Fix too strict type definitions 2018-07-14 18:23:05 +02:00
e76606d0a3 Static test fixes 2018-07-14 17:23:18 +02:00
0614c12eef Fix more type bugs 2018-07-14 14:41:15 +02:00
39f299e211 Fix formatting 2018-07-14 14:22:25 +02:00
7d8a68b589 Minor code fixes 2018-07-14 14:09:41 +02:00
cb76bea3e7 Fix missing use 2018-07-14 13:45:25 +02:00
d9ecb8400f Reduce potential errors 2018-07-14 13:40:49 +02:00
94afffec8e Remove whitespace 2018-07-12 23:33:32 +02:00
83e3c199cd Check whitespace commit 2018-07-12 20:40:53 +02:00
20b3303623 Check whitespace commit 2018-07-12 20:36:43 +02:00
20456981d6 Handle invalid type asignment 2018-07-12 20:29:56 +02:00
fce9ad82ba Handle invalid type asignment 2018-07-12 20:28:13 +02:00
d494da3d3b Handle invalid type asignment 2018-07-12 20:27:02 +02:00
5639b7936d UriFactory kills this test. Look at it later 2018-07-07 19:42:07 +02:00
91a4732c1b Fix bugs 2018-07-07 19:41:44 +02:00
46c5647463 Fix double ? in uri bug 2018-07-06 21:32:57 +02:00
f6dd0571a0 Add uri parsing 2018-07-06 20:44:32 +02:00
c681d9697f Improve module list results and improve types 2018-07-06 20:44:21 +02:00
4c178b17a5 Fix return bug 2018-07-01 16:14:34 +02:00
889d6e4469 Fix bugs and make js tests same as php tests 2018-06-30 23:04:00 +02:00
85dd4a6d97 Split up tests 2018-06-26 21:08:26 +02:00
2b8c38f474 Fix bad tests 2018-06-24 17:56:25 +02:00
712c5a4a40 ignore linux directory view 2018-06-24 17:30:50 +02:00
9ad5fda8c4 Hook test 2018-06-24 17:28:53 +02:00
acfcba9d67 Move default definitions 2018-06-24 10:09:15 +02:00
b8da0f8c19 added extension 2018-06-22 21:58:14 +02:00
128203bb17 Remove invalid examples 2018-06-22 21:58:00 +02:00
563e6c8631 Fixed line endings 2018-06-22 16:31:00 +02:00
3ab5c4ce95 Remove empty line 2018-06-22 16:04:43 +02:00
7900333d41 Fix required php version 2018-06-20 19:53:24 +02:00
f0f505301e Add additional meta tag renderings e.g. for fb, twitter etc. 2018-06-20 19:53:08 +02:00
36f63aa97f Start implementing eigenvaluedecomposition 2018-06-05 18:56:17 +02:00
9bf5ed087d Extend form error levels 2018-06-03 16:49:01 +02:00
c2df3a1ffd Fix bugs after adjustments 2018-06-03 16:34:38 +02:00
6f452f25e8 Code and docblock optimizations 2018-06-03 16:04:13 +02:00
ffda1a2724 Fix docblocks 2018-06-03 16:03:40 +02:00
3aa3c6b0dd Handle open todos 2018-06-03 14:22:05 +02:00
7db81b9bdd Fix spacing 2018-06-03 10:35:15 +02:00
381ce558b9 Remove old todo 2018-06-03 10:34:56 +02:00
35ce2562c7 add type hint 2018-06-03 10:34:35 +02:00
55013d86cd Remove old todos 2018-06-03 10:34:09 +02:00
a4b6411fcd Implement NullCommit 2018-06-03 10:33:27 +02:00
905dbe3b48 Removed unused code part 2018-06-03 10:32:52 +02:00
e6e605f43a Add docblock 2018-06-01 09:36:01 +02:00
9aa8a9318c Optimize module init 2018-06-01 09:35:50 +02:00
ba957b4dcf Improve array type hint 2018-05-31 20:06:54 +02:00
e611105b60 Added independent symmetry check 2018-05-31 17:38:36 +02:00
31209d2b30 Implement basic localization db mapper 2018-05-30 22:35:42 +02:00
a9bb4b9224 Remove line breaks 2018-05-30 22:34:33 +02:00
1b0d170052 Use root namespace and cleanup 2018-05-30 13:40:28 +02:00
37add470eb Remove whitespace 2018-05-21 22:31:14 +02:00
e36f56da30 Fix array path bugs 2018-05-21 20:03:06 +02:00
71a13da619 Optimize mapper loops 2018-05-21 17:48:41 +02:00
aa89b83746 Reformat 2018-05-21 11:13:56 +02:00
bc3d5ed4c7 Draft datamapper array support 2018-05-21 10:51:58 +02:00
b1b51b0281 Bug fixes with install scripts 2018-05-20 11:54:02 +02:00
f2591bff06 PHP CS fixes 2018-05-14 21:17:44 +02:00
59d3f98110 Make classes final 2018-05-11 21:33:24 +02:00
aef7699ba2 Implement underline 2018-05-09 20:43:03 +02:00
bb30edde28 Fix wrong change time 2018-04-24 19:26:35 +02:00
b78c86a0ac Allow exclude pattern 2018-04-24 19:26:20 +02:00
bcf3b761cd Fix unicode check 2018-04-24 19:25:59 +02:00
9801d86b61 Fix complex and matrix 2018-04-20 19:35:57 +02:00
23f24cf467 Implement disabled functions 2018-04-13 22:10:54 +02:00
916497f329 Implement filter 2018-04-13 22:10:40 +02:00
184e407201 Fix #29 2018-04-13 21:04:48 +02:00
5ab51d66b7 Fix #152 2018-04-11 20:57:36 +02:00
3ca7538977 Improve array parser cs 2018-04-01 18:54:28 +02:00
592bd52667 Implement hook support 2018-04-01 18:54:13 +02:00
566d8e8c27 Don't use EOL 2018-03-31 22:19:33 +02:00
a47d784f66 Reduce array parsing edge case bugs 2018-03-31 22:17:27 +02:00
051c123b77 Improve array parsing 2018-03-31 21:58:13 +02:00
e4531d3726 phpstan fixes 2018-03-30 18:37:23 +02:00
e7385fdf9d Remove vendor / not working 2018-03-30 14:42:57 +02:00
d9c7bd0b50 Phpstan fixes 2018-03-30 13:32:15 +02:00
f23734464d Fix extension loaded test 2018-03-30 11:14:53 +02:00
44bb3480ac More extension tests 2018-03-30 10:29:32 +02:00
24f28dc82c Add extension test 2018-03-30 10:24:24 +02:00
8db0fca114 Fix array index 2018-03-30 09:59:32 +02:00
85e79113fd Fix invalid type 2018-03-30 09:39:29 +02:00
cc22beab3e
Fix indention 2018-03-29 13:48:00 +02:00
3c466931c7
Allow multiple paths for exists 2018-03-29 13:39:23 +02:00
067af207df
Fix path 2018-03-29 13:37:56 +02:00
d37433c026
Implement multiple paths for autoloading 2018-03-29 13:36:55 +02:00
2ec800fe62 Fix unit test bugs 2018-03-28 23:11:22 +02:00
d5fd2c4827 Change to php version 7.2 requirement 2018-03-27 19:09:47 +02:00
92271d2981 If json and empty print empty array 2018-03-24 19:11:23 +01:00
8067e42f78 Type hint fixes 2018-03-24 11:17:45 +01:00
af0a980d1b Return type fixes 2018-03-16 12:08:35 +01:00
5f385e44c0 Add public/private to const 2018-03-16 08:47:43 +01:00
6f6a0e1bd1 Type fixes 2018-03-14 18:12:08 +01:00
7b8b0cc227 Merge branch 'develop' of https://github.com/Orange-Management/phpOMS into develop 2018-03-14 17:12:33 +01:00
d3258357e0
Fix return type docblock 2018-03-14 10:00:04 +01:00
1bc4593654
Remove empty construct 2018-03-14 09:57:41 +01:00
35b45cbb5b
Remove nullable for default null para 2018-03-14 09:50:58 +01:00
1cd1ee0e10 phpstan fixes 2018-03-13 23:35:20 +01:00
3b45692ff1 Nullable+void typehint 2018-03-13 20:55:49 +01:00
301aa59d61 Test phpstan 2018-03-13 20:43:22 +01:00
7064cd6e7e
Permission fix 2018-03-13 13:02:45 +01:00
aae0de25f1 Adjust permission handling to string 2018-03-09 22:21:21 +01:00
1022824e47 Tests+docblock 2018-03-04 12:11:46 +01:00
de6120b267 Tests, docblocks & improvements 2018-03-03 11:15:34 +01:00
24252655eb Fix restructured datastorage 2018-03-01 20:31:02 +01:00
b810e72588 Start datastorage restructure 2018-02-28 21:43:29 +01:00
797b1c1f00 Added depreciation+tests 2018-02-28 20:37:54 +01:00
1f4df655ad Fix path 2018-02-26 20:12:25 +01:00
ab96277fb1 Reduce isset use 2018-02-26 20:05:02 +01:00
3c3c7fe251 Remove is_null 2018-02-26 19:46:50 +01:00
5b243ab2da Turn exceptions in false returns 2018-02-26 19:46:28 +01:00
2bdc9410b7 Fix package name 2018-02-26 19:45:35 +01:00
6b68c42c33
Update ChiSquaredDistributionTest.php 2018-02-26 14:58:05 +01:00
dd99496d75
Update CauchyDistributionTest.php 2018-02-26 14:41:10 +01:00
49ecbc3259
Update CauchyDistribution.php 2018-02-26 14:39:52 +01:00
2305380945 More tests (math tests) and fixes 2018-02-25 16:12:31 +01:00
3aedae39e4 Fix functio name 2018-02-23 19:35:29 +01:00
9382c30d35 Add gitattributes 2018-02-23 18:05:38 +01:00
03208332ae Fix error bugs 2018-02-23 17:55:17 +01:00
e97bd27eb0
Semicolon bug fix 2018-02-23 11:12:53 +01:00
5185b52c91
Added optional mean value
Now it is possible to pass pre calculated means in case the arithmeticMean shouldn't be used
2018-02-23 11:12:07 +01:00
a08c63a021
Formatting fix 2018-02-23 10:56:35 +01:00
66a5510873
Fix int/float bug 2018-02-23 10:55:35 +01:00
59b701a6be
Fix formatting 2018-02-23 10:54:58 +01:00
cc682b1945
Added mean error test 2018-02-23 10:49:00 +01:00
b3b7391712
Added power test 2018-02-23 10:39:14 +01:00
bf9625fc0b
Update Functions.php 2018-02-23 10:36:13 +01:00
a1b78de312
Pulled out square function 2018-02-23 10:35:16 +01:00
3f438238e7
Added power function on arrays 2018-02-23 10:34:01 +01:00
a982bb432a
Started to implement tests 2018-02-23 10:29:53 +01:00
cb374f663a Add latex formulas 2018-02-22 21:12:36 +01:00
510842727c More unit tests and fix statistic 2018-02-22 20:48:13 +01:00
cc904e772a Add more tests 2018-02-22 13:54:08 +01:00
c43d83d8c0 Add more tests and fix bugs 2018-02-21 21:16:35 +01:00
ae87bc9ab5 allow scalar delete 2018-02-18 10:47:28 +01:00
fdff9da488 phpcs fixes 2018-02-17 22:05:29 +01:00
a15a1b229e phpcs fixes 2018-02-17 21:53:13 +01:00
675d3fa808 phpcs fixes 2018-02-17 21:38:39 +01:00
a8afbc5cc8 phpcs fixes 2018-02-17 19:51:19 +01:00
5a7c138be0 docblocks 2018-02-17 18:31:23 +01:00
4c04ce01c2 Fix/test more sql injections 2018-02-17 09:39:29 +01:00
f7ebd61f40 Fix value injection 2018-02-17 09:18:46 +01:00
e90ad9477a phpcs fixes 2018-02-16 18:27:42 +01:00
2fbf79bce0 phpcs fixes 2018-02-16 16:17:01 +01:00
3059003191 phpcs fixes 2018-02-16 15:28:07 +01:00
11c7b0e626 docblock param alignment 2018-02-16 13:42:35 +01:00
e1ef45da2a code fixes 2018-02-16 13:34:41 +01:00
aae3cc3a06 Type cast fixes 2018-02-15 20:44:57 +01:00
f1121dcc9b Fix strict_types 2018-02-15 20:27:58 +01:00
b77ad7e5c5 q 2018-02-14 18:44:43 +01:00
e3b14015fc Improve increments 2018-02-10 21:52:20 +01:00
1fe4b18266 Fix class names 2018-02-10 20:46:52 +01:00
5233b395d0 Improve coc and contribution guide 2018-02-06 20:03:43 +01:00
579f8d9565 Timing bug fix 2018-02-04 20:55:28 +01:00
2212 changed files with 243831 additions and 42380 deletions

37
.gitattributes vendored Executable file
View File

@ -0,0 +1,37 @@
* text=false
*.php ident
# Force the following filetypes to have unix eols, so Windows does not break them
*.php text eol=lf
*.js text eol=lf
*.sh text eol=lf
*.css text eol=lf
*.md text eol=lf
*.txt text eol=lf
*.htaccess text eol=lf
*.json text eol=lf
*.c text eol=lf
*.cpp text eol=lf
*.h text eol=lf
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.mov binary
*.mp4 binary
*.mp3 binary
*.flv binary
*.fla binary
*.swf binary
*.gz binary
*.zip binary
*.7z binary
*.ttf binary
*.eot binary
*.woff binary
*.pyc binary
*.pdf binary
*.dat binary
*.z binary

View File

@ -1 +0,0 @@
A developer and contribution documentation can be found at https://orange-management.gitbooks.io/developer-guide/content/index.html.

11
.github/dependabot.yml vendored Executable file
View File

@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "composer" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"

13
.github/workflows/greetings.yml vendored Executable file
View File

@ -0,0 +1,13 @@
name: Greetings
on: [pull_request, issues]
jobs:
greeting:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: 'Thank you for createing this issue. We will check it as soon as possible.'
pr-message: 'Thank you for your pull request. We will check it as soon as possible.'

24
.github/workflows/image.yml vendored Executable file
View File

@ -0,0 +1,24 @@
name: Compress images
on:
push:
paths:
- '**.jpg'
- '**.png'
- '**.webp'
pull_request:
paths:
- '**.jpg'
- '**.png'
- '**.webp'
jobs:
build:
name: calibreapp/image-actions
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@main
- name: Compress Images
uses: calibreapp/image-actions@main
with:
githubToken: ${{ secrets.GH_TOKEN }}

11
.github/workflows/main.yml vendored Executable file
View File

@ -0,0 +1,11 @@
name: CI
on: [push, pull_request]
jobs:
general_module_workflow_php:
uses: Karaka-Management/Karaka/.github/workflows/php_template.yml@develop
secrets:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_PAT: ${{ secrets.GH_PAT }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

18
.gitignore vendored Normal file → Executable file
View File

@ -1 +1,17 @@
*.log *.log
.directory
Build
*.cache
.directory
Vagrantfile
vendor
bower_components
node_modules
*.log
.vagrant
.vscode
.sass-cache
cache
Cache
Libraries
.idea*.cache

540
Account/Account.php Normal file → Executable file
View File

@ -1,22 +1,20 @@
<?php <?php
/** /**
* Orange Management * Jingga
* *
* PHP Version 7.1 * PHP Version 8.2
* *
* @package phpOMS\Account * @package phpOMS\Account
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 1.0 * @license OMS License 2.0
* @version 1.0.0 * @version 1.0.0
* @link http://website.orange-management.de * @link https://jingga.app
*/ */
declare(strict_types = 1); declare(strict_types=1);
namespace phpOMS\Account; namespace phpOMS\Account;
use phpOMS\Contract\ArrayableInterface;
use phpOMS\Localization\Localization; use phpOMS\Localization\Localization;
use phpOMS\Localization\NullLocalization;
use phpOMS\Validation\Network\Email; use phpOMS\Validation\Network\Email;
/** /**
@ -25,21 +23,20 @@ use phpOMS\Validation\Network\Email;
* The account class is the base model for accounts. This model contains the most common account * The account class is the base model for accounts. This model contains the most common account
* information. This model is not comparable to a profile which contains much more information. * information. This model is not comparable to a profile which contains much more information.
* *
* @package phpOMS\Account * @package phpOMS\Account
* @license OMS License 1.0 * @license OMS License 2.0
* @link http://website.orange-management.de * @link https://jingga.app
* @since 1.0.0 * @since 1.0.0
*/ */
class Account implements ArrayableInterface, \JsonSerializable class Account implements \JsonSerializable
{ {
/** /**
* Id. * Id.
* *
* @var int * @var int
* @since 1.0.0 * @since 1.0.0
*/ */
protected $id = 0; public int $id = 0;
/** /**
* Names. * Names.
@ -47,7 +44,7 @@ class Account implements ArrayableInterface, \JsonSerializable
* @var string * @var string
* @since 1.0.0 * @since 1.0.0
*/ */
protected $name1 = ''; public string $name1 = '';
/** /**
* Names. * Names.
@ -55,7 +52,7 @@ class Account implements ArrayableInterface, \JsonSerializable
* @var string * @var string
* @since 1.0.0 * @since 1.0.0
*/ */
protected $name2 = ''; public string $name2 = '';
/** /**
* Names. * Names.
@ -63,7 +60,7 @@ class Account implements ArrayableInterface, \JsonSerializable
* @var string * @var string
* @since 1.0.0 * @since 1.0.0
*/ */
protected $name3 = ''; public string $name3 = '';
/** /**
* Email. * Email.
@ -71,7 +68,7 @@ class Account implements ArrayableInterface, \JsonSerializable
* @var string * @var string
* @since 1.0.0 * @since 1.0.0
*/ */
protected $email = ''; public string $email = '';
/** /**
* Ip. * Ip.
@ -81,15 +78,15 @@ class Account implements ArrayableInterface, \JsonSerializable
* @var string * @var string
* @since 1.0.0 * @since 1.0.0
*/ */
protected $origin = ''; public string $origin = '';
/** /**
* Login. * Login.
* *
* @var string * @var null|string
* @since 1.0.0 * @since 1.0.0
*/ */
protected $login = ''; public ?string $login = null;
/** /**
* Last activity. * Last activity.
@ -97,31 +94,23 @@ class Account implements ArrayableInterface, \JsonSerializable
* @var \DateTime * @var \DateTime
* @since 1.0.0 * @since 1.0.0
*/ */
protected $lastActive = null; public \DateTime $lastActive;
/** /**
* Last activity. * Last activity.
* *
* @var \DateTime * @var \DateTimeImmutable
* @since 1.0.0 * @since 1.0.0
*/ */
protected $createdAt = null; public \DateTimeImmutable $createdAt;
/**
* Permissions.
*
* @var PermissionAbstract[]
* @since 1.0.0
*/
protected $permissions = [];
/** /**
* Groups. * Groups.
* *
* @var int[] * @var Group[]
* @since 1.0.0 * @since 1.0.0
*/ */
protected $groups = []; public array $groups = [];
/** /**
* Password. * Password.
@ -129,7 +118,7 @@ class Account implements ArrayableInterface, \JsonSerializable
* @var string * @var string
* @since 1.0.0 * @since 1.0.0
*/ */
protected $password = ''; public string $password = '';
/** /**
* Account type. * Account type.
@ -137,7 +126,7 @@ class Account implements ArrayableInterface, \JsonSerializable
* @var int * @var int
* @since 1.0.0 * @since 1.0.0
*/ */
protected $type = AccountType::USER; public int $type = AccountType::USER;
/** /**
* Account status. * Account status.
@ -145,7 +134,7 @@ class Account implements ArrayableInterface, \JsonSerializable
* @var int * @var int
* @since 1.0.0 * @since 1.0.0
*/ */
protected $status = AccountStatus::INACTIVE; public int $status = AccountStatus::INACTIVE;
/** /**
* Localization. * Localization.
@ -153,184 +142,43 @@ class Account implements ArrayableInterface, \JsonSerializable
* @var Localization * @var Localization
* @since 1.0.0 * @since 1.0.0
*/ */
protected $l11n = null; public Localization $l11n;
use PermissionHandlingTrait;
/** /**
* Constructor. * Has permission.
* *
* The constructor automatically sets the created date as well as the last activity to now. * @param int $permission Permission
* @param int|null $unit Unit
* @param int|null $app App
* @param string|null $module Module
* @param int|null $category Category
* @param int|null $element Element
* @param int|null $component Component
* *
* @param int $id Account id * @return bool
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function __construct(int $id = 0) public function hasPermission(
int $permission,
?int $unit = null,
?int $app = null,
?string $module = null,
?int $category = null,
?int $element = null,
?int $component = null
) : bool
{ {
$this->createdAt = new \DateTime('now'); foreach ($this->groups as $group) {
$this->lastActive = new \DateTime('now'); if ($group->hasPermission($permission, $unit, $app, $module, $category, $element, $component)) {
$this->id = $id; return true;
$this->l11n = new NullLocalization(); }
} }
/**
* Get account id.
*
* @return int Account id
*
* @since 1.0.0
*/
public function getId() : int
{
return $this->id;
}
/**
* Get localization.
*
* Every account can have a different localization which can be accessed here.
*
* @return Localization
*
* @since 1.0.0
*/
public function getL11n() : Localization
{
return $this->l11n;
}
/**
* Get groups.
*
* Every account can belong to multiple groups.
* These groups usually are used for permissions and categorize accounts.
*
* @return array Returns array of all groups
*
* @since 1.0.0
*/
public function getGroups() : array
{
return $this->groups;
}
/**
* Add group.
*
* @param mixed $group Group to add
*
* @return void
*
* @since 1.0.0
*/
public function addGroup($group) /* : void */
{
$this->groups[] = $group;
}
/**
* Set localization.
*
* @param Localization $l11n Localization
*
* @return void
*
* @since 1.0.0
*/
public function setL11n(Localization $l11n) /* : void */
{
$this->l11n = $l11n;
}
/**
* Set permissions.
*
* The method accepts an array of permissions. All existing permissions are replaced.
*
* @param PermissionAbstract[] $permissions
*
* @return void
*
* @since 1.0.0
*/
public function setPermissions(array $permissions) /* : void */
{
$this->permissions = $permissions;
}
/**
* Add permissions.
*
* Adds permissions to the account
*
* @param PermissionAbstract[] $permissions Array of permissions to add to the account
*
* @return void
*
* @since 1.0.0
*/
public function addPermissions(array $permissions) /* : void */
{
$this->permissions = array_merge($this->permissions, $permissions);
}
/**
* Add permission.
*
* Adds a single permission to the account
*
* @param PermissionAbstract $permission Permission to add to the account
*
* @return void
*
* @since 1.0.0
*/
public function addPermission(PermissionAbstract $permission) /* : void */
{
$this->permissions[] = $permission;
}
/**
* Get permissions.
*
* @return array
*
* @since 1.0.0
*/
public function getPermissions() : array
{
return $this->permissions;
}
/**
* Has permissions.
*
* Checks if the account has a permission defined
*
* @param int $permission Permission to check
* @param int $unit Unit Unit to check (null if all are acceptable)
* @param string $app App App to check (null if all are acceptable)
* @param int $module Module Module to check (null if all are acceptable)
* @param int $type Type (e.g. customer) (null if all are acceptable)
* @param int $element (e.g. customer id) (null if all are acceptable)
* @param int $component (e.g. address) (null if all are acceptable)
*
* @return bool Returns true if the account has the permission, false otherwise
*
* @since 1.0.0
*/
public function hasPermission(int $permission, int $unit = null, string $app = null, int $module = null, int $type = null, $element = null, $component = null) : bool
{
$app = isset($app) ? strtolower($app) : $app;
foreach ($this->permissions as $p) { foreach ($this->permissions as $p) {
if (($p->getUnit() === $unit || $p->getUnit() === null || !isset($unit)) if ($p->hasPermission($permission, $unit, $app, $module, $category, $element, $component)) {
&& ($p->getApp() === $app || $p->getApp() === null || !isset($app))
&& ($p->getModule() === $module || $p->getModule() === null || !isset($module))
&& ($p->getType() === $type || $p->getType() === null || !isset($type))
&& ($p->getElement() === $element || $p->getElement() === null || !isset($element))
&& ($p->getComponent() === $component || $p->getComponent() === null || !isset($component))
&& ($p->getPermission() | $permission) === $p->getPermission()
) {
return true; return true;
} }
} }
@ -339,101 +187,109 @@ class Account implements ArrayableInterface, \JsonSerializable
} }
/** /**
* Get name. * Constructor.
* *
* @return string * The constructor automatically sets the created date as well as the last activity to now.
* *
* @since 1.0.0 * @param int $id Account id
*
* @since 1.0.0
*/ */
public function getName() : string public function __construct(int $id = 0)
{ {
return $this->login; $this->createdAt = new \DateTimeImmutable('now');
$this->lastActive = new \DateTime('now');
$this->id = $id;
$this->l11n = new Localization();
} }
/** /**
* Get name1. * Get account id.
* *
* @return string * @return int Account id
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function getName1() : string public function getId() : int
{ {
return $this->name1; return $this->id;
} }
/** /**
* Set name1. * Get groups.
* *
* @param string $name Name * Every account can belong to multiple groups.
* These groups usually are used for permissions and categorize accounts.
*
* @return Group[] Returns array of all groups
*
* @since 1.0.0
*/
public function getGroups() : array
{
return $this->groups;
}
/**
* Get ids of groups
*
* @return int[]
*
* @since 1.0.0
*/
public function getGroupIds() : array
{
/*
$ids = [];
foreach ($this->groups as $group) {
$ids[] = $group->id;
}
return $ids;
*/
return \array_keys($this->groups);
}
/**
* Add group.
*
* @param Group $group Group to add
* *
* @return void * @return void
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function setName1(string $name) /* : void */ public function addGroup(Group $group) : void
{ {
$this->name1 = $name; $this->groups[] = $group;
} }
/** /**
* Get name2. * User has group.
* *
* @return string * @param int $id Group id
* *
* @since 1.0.0 * @return bool
*
* @since 1.0.0
*/ */
public function getName2() : string public function hasGroup(int $id) : bool
{ {
return $this->name2; foreach ($this->groups as $group) {
} if ($group->id === $id) {
return true;
}
}
/** return false;
* Set name2.
*
* @param string $name Name
*
* @return void
*
* @since 1.0.0
*/
public function setName2(string $name) /* : void */
{
$this->name2 = $name;
}
/**
* Get name3.
*
* @return string
*
* @since 1.0.0
*/
public function getName3() : string
{
return $this->name3;
}
/**
* Set name3.
*
* @param string $name Name
*
* @return void
*
* @since 1.0.0
*/
public function setName3(string $name) /* : void */
{
$this->name3 = $name;
} }
/** /**
* Get email. * Get email.
* *
* @return string * @return string Returns the email address
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function getEmail() : string public function getEmail() : string
{ {
@ -449,103 +305,27 @@ class Account implements ArrayableInterface, \JsonSerializable
* *
* @throws \InvalidArgumentException Exception is thrown if the provided string is not a valid email * @throws \InvalidArgumentException Exception is thrown if the provided string is not a valid email
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function setEmail(string $email) /* : void */ public function setEmail(string $email) : void
{ {
if (!Email::isValid($email)) { if ($email !== '' && !Email::isValid($email)) {
throw new \InvalidArgumentException(); throw new \InvalidArgumentException();
} }
$this->email = mb_strtolower($email); $this->email = \mb_strtolower($email);
}
/**
* Get status.
*
* AccountStatus
*
* @return int
*
* @since 1.0.0
*/
public function getStatus() : int
{
return $this->status;
}
/**
* Get status.
*
* @param int $status Status
*
* @return void
*
* @since 1.0.0
*/
public function setStatus(int $status) /* : void */
{
if (!AccountStatus::isValidValue($status)) {
throw new \InvalidArgumentException();
}
$this->status = $status;
}
/**
* Get type.
*
* AccountType
*
* @return int
*
* @since 1.0.0
*/
public function getType() : int
{
return $this->type;
}
/**
* Get type.
*
* @param int $type Type
*
* @return void
*
* @since 1.0.0
*/
public function setType(int $type) /* : void */
{
if (!AccountType::isValidValue($type)) {
throw new \InvalidArgumentException();
}
$this->type = $type;
} }
/** /**
* Get last activity. * Get last activity.
* *
* @return \DateTime * @return \DateTimeInterface
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function getLastActive() : \DateTime public function getLastActive() : \DateTimeInterface
{ {
return $this->lastActive ?? $this->getCreatedAt(); return $this->lastActive ?? $this->createdAt;
}
/**
* Get created at.
*
* @return \DateTime
*
* @since 1.0.0
*/
public function getCreatedAt() : \DateTime
{
return $this->createdAt ?? new \DateTime('NOW');
} }
/** /**
@ -555,31 +335,19 @@ class Account implements ArrayableInterface, \JsonSerializable
* *
* @return void * @return void
* *
* @throws \Exception * @throws \Exception Throws this exception if the password_hash function fails
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function generatePassword(string $password) /* : void */ public function generatePassword(string $password) : void
{ {
$this->password = \password_hash($password, \PASSWORD_DEFAULT); $temp = \password_hash($password, \PASSWORD_BCRYPT);
if ($this->password === false) { if ($temp === false) {
throw new \Exception(); throw new \Exception('Internal password_hash error.'); // @codeCoverageIgnore
} }
}
/** $this->password = $temp;
* Set name.
*
* @param string $name Name
*
* @return void
*
* @since 1.0.0
*/
public function setName(string $name) /* : void */
{
$this->login = $name;
} }
/** /**
@ -587,23 +355,23 @@ class Account implements ArrayableInterface, \JsonSerializable
* *
* @return void * @return void
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function updateLastActive() /* : void */ public function updateLastActive() : void
{ {
$this->lastActive = new \DateTime('NOW'); $this->lastActive = new \DateTime('now');
} }
/** /**
* Get string representation. * Get string representation.
* *
* @return string * @return string Returns the json_encode of this object
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function __toString() public function __toString() : string
{ {
return json_encode($this->toArray()); return (string) \json_encode($this->toArray());
} }
/** /**
@ -612,8 +380,8 @@ class Account implements ArrayableInterface, \JsonSerializable
public function toArray() : array public function toArray() : array
{ {
return [ return [
'id' => $this->id, 'id' => $this->id,
'name' => [ 'name' => [
$this->name1, $this->name1,
$this->name2, $this->name2,
$this->name3, $this->name3,
@ -628,13 +396,9 @@ class Account implements ArrayableInterface, \JsonSerializable
} }
/** /**
* Json serialize. * {@inheritdoc}
*
* @return array
*
* @since 1.0.0
*/ */
public function jsonSerialize() public function jsonSerialize() : mixed
{ {
return $this->toArray(); return $this->toArray();
} }

61
Account/AccountManager.php Normal file → Executable file
View File

@ -1,16 +1,16 @@
<?php <?php
/** /**
* Orange Management * Jingga
* *
* PHP Version 7.1 * PHP Version 8.2
* *
* @package phpOMS\Account * @package phpOMS\Account
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 1.0 * @license OMS License 2.0
* @version 1.0.0 * @version 1.0.0
* @link http://website.orange-management.de * @link https://jingga.app
*/ */
declare(strict_types = 1); declare(strict_types=1);
namespace phpOMS\Account; namespace phpOMS\Account;
@ -20,23 +20,22 @@ use phpOMS\DataStorage\Session\SessionInterface;
/** /**
* Account manager class. * Account manager class.
* *
* The account manager is used to manage multiple accounts. * The account manager is used to manage accounts.
* *
* @package phpOMS\Account * @package phpOMS\Account
* @license OMS License 1.0 * @license OMS License 2.0
* @link http://website.orange-management.de * @link https://jingga.app
* @since 1.0.0 * @since 1.0.0
*/ */
class AccountManager implements \Countable final class AccountManager implements \Countable
{ {
/** /**
* Accounts. * Accounts.
* *
* @var Account[] * @var Account[]
* @since 1.0.0 * @since 1.0.0
*/ */
private $accounts = []; private array $accounts = [];
/** /**
* Session. * Session.
@ -44,14 +43,14 @@ class AccountManager implements \Countable
* @var SessionInterface * @var SessionInterface
* @since 1.0.0 * @since 1.0.0
*/ */
private $session = null; private SessionInterface $session;
/** /**
* Constructor. * Constructor.
* *
* @param SessionInterface $session Session * @param SessionInterface $session Session
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function __construct(SessionInterface $session) public function __construct(SessionInterface $session)
{ {
@ -65,15 +64,15 @@ class AccountManager implements \Countable
* *
* @return Account * @return Account
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function get(int $id = 0) : Account public function get(int $id = 0) : Account
{ {
if ($id === 0) { if ($id === 0) {
$account = new Account(Auth::authenticate($this->session)); $account = new Account(Auth::authenticate($this->session));
if (!isset($this->accounts[$account->getId()])) { if (!isset($this->accounts[$account->id])) {
$this->accounts[$account->getId()] = $account; $this->accounts[$account->id] = $account;
} }
return $account; return $account;
@ -87,14 +86,14 @@ class AccountManager implements \Countable
* *
* @param Account $account Account * @param Account $account Account
* *
* @return bool * @return bool Returns true if the account could be added otherwise false is returned
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function add(Account $account) : bool public function add(Account $account) : bool
{ {
if (!isset($this->accounts[$account->getId()])) { if (!isset($this->accounts[$account->id])) {
$this->accounts[$account->getId()] = $account; $this->accounts[$account->id] = $account;
return true; return true;
} }
@ -107,9 +106,9 @@ class AccountManager implements \Countable
* *
* @param int $id Account id * @param int $id Account id
* *
* @return bool * @return bool Returns true if the account could be removed otherwise false
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function remove(int $id) : bool public function remove(int $id) : bool
{ {
@ -125,12 +124,12 @@ class AccountManager implements \Countable
/** /**
* Get accounts count. * Get accounts count.
* *
* @return int * @return int Returns the amount of accounts in the manager (>= 0)
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function count() : int public function count() : int
{ {
return count($this->accounts); return \count($this->accounts);
} }
} }

35
Account/AccountStatus.php Normal file → Executable file
View File

@ -1,16 +1,16 @@
<?php <?php
/** /**
* Orange Management * Jingga
* *
* PHP Version 7.1 * PHP Version 8.2
* *
* @package phpOMS\Account * @package phpOMS\Account
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 1.0 * @license OMS License 2.0
* @version 1.0.0 * @version 1.0.0
* @link http://website.orange-management.de * @link https://jingga.app
*/ */
declare(strict_types = 1); declare(strict_types=1);
namespace phpOMS\Account; namespace phpOMS\Account;
@ -19,15 +19,18 @@ use phpOMS\Stdlib\Base\Enum;
/** /**
* Account status enum. * Account status enum.
* *
* @package phpOMS\Account * @package phpOMS\Account
* @license OMS License 1.0 * @license OMS License 2.0
* @link http://website.orange-management.de * @link https://jingga.app
* @since 1.0.0 * @since 1.0.0
*/ */
abstract class AccountStatus extends Enum abstract class AccountStatus extends Enum
{ {
/* public */ const ACTIVE = 1; public const ACTIVE = 1;
/* public */ const INACTIVE = 2;
/* public */ const TIMEOUT = 3; public const INACTIVE = 2;
/* public */ const BANNED = 4;
public const TIMEOUT = 3;
public const BANNED = 4;
} }

29
Account/AccountType.php Normal file → Executable file
View File

@ -1,16 +1,16 @@
<?php <?php
/** /**
* Orange Management * Jingga
* *
* PHP Version 7.1 * PHP Version 8.2
* *
* @package phpOMS\Account * @package phpOMS\Account
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 1.0 * @license OMS License 2.0
* @version 1.0.0 * @version 1.0.0
* @link http://website.orange-management.de * @link https://jingga.app
*/ */
declare(strict_types = 1); declare(strict_types=1);
namespace phpOMS\Account; namespace phpOMS\Account;
@ -19,13 +19,14 @@ use phpOMS\Stdlib\Base\Enum;
/** /**
* Account type enum. * Account type enum.
* *
* @package phpOMS\Account * @package phpOMS\Account
* @license OMS License 1.0 * @license OMS License 2.0
* @link http://website.orange-management.de * @link https://jingga.app
* @since 1.0.0 * @since 1.0.0
*/ */
abstract class AccountType extends Enum abstract class AccountType extends Enum
{ {
/* public */ const USER = 0; public const USER = 0;
/* public */ const GROUP = 1;
public const GROUP = 1;
} }

174
Account/Group.php Normal file → Executable file
View File

@ -1,63 +1,60 @@
<?php <?php
/** /**
* Orange Management * Jingga
* *
* PHP Version 7.1 * PHP Version 8.2
* *
* @package phpOMS\Account * @package phpOMS\Account
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 1.0 * @license OMS License 2.0
* @version 1.0.0 * @version 1.0.0
* @link http://website.orange-management.de * @link https://jingga.app
*/ */
declare(strict_types = 1); declare(strict_types=1);
namespace phpOMS\Account; namespace phpOMS\Account;
use phpOMS\Contract\ArrayableInterface;
/** /**
* Account group class. * Account group class.
* *
* @package phpOMS\Account * @package phpOMS\Account
* @license OMS License 1.0 * @license OMS License 2.0
* @link http://website.orange-management.de * @link https://jingga.app
* @since 1.0.0 * @since 1.0.0
*/ */
class Group implements ArrayableInterface, \JsonSerializable class Group implements \JsonSerializable
{ {
/** /**
* Account id. * Group id.
* *
* @var int * @var int
* @since 1.0.0 * @since 1.0.0
*/ */
protected $id = 0; public int $id = 0;
/** /**
* Account name. * Group name.
* *
* @var string * @var string
* @since 1.0.0 * @since 1.0.0
*/ */
protected $name = ''; public string $name = '';
/** /**
* Account name. * Group name.
* *
* @var string * @var string
* @since 1.0.0 * @since 1.0.0
*/ */
protected $description = ''; public string $description = '';
/** /**
* Account name. * Group members.
* *
* @var int * @var array
* @since 1.0.0 * @since 1.0.0
*/ */
protected $members = []; public array $members = [];
/** /**
* Parents. * Parents.
@ -65,7 +62,7 @@ class Group implements ArrayableInterface, \JsonSerializable
* @var int[] * @var int[]
* @since 1.0.0 * @since 1.0.0
*/ */
protected $parents = []; public array $parents = [];
/** /**
* Group status. * Group status.
@ -73,131 +70,32 @@ class Group implements ArrayableInterface, \JsonSerializable
* @var int * @var int
* @since 1.0.0 * @since 1.0.0
*/ */
protected $status = GroupStatus::INACTIVE; public int $status = GroupStatus::INACTIVE;
/** use PermissionHandlingTrait;
* Permissions.
*
* @var int[]
* @since 1.0.0
*/
protected $permissions = [];
/**
* Constructor.
*
* @since 1.0.0
*/
public function __construct()
{
}
/** /**
* Get group id. * Get group id.
* *
* @return int * @return int Returns the id of the group
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function getId() : int public function getId() : int
{ {
return $this->id; return $this->id;
} }
/**
* Get group name.
*
* @return string
*
* @since 1.0.0
*/
public function getName() : string
{
return $this->name;
}
/**
* Set group name.
*
* @param string $name Group name
*
* @return void
*
* @since 1.0.0
*/
public function setName(string $name) /* : void */
{
$this->name = $name;
}
/**
* Get group description.
*
* @return string
*
* @since 1.0.0
*/
public function getDescription() : string
{
return $this->description;
}
/**
* Set group description.
*
* @param string $description Group description
*
* @return void
*
* @since 1.0.0
*/
public function setDescription(string $description) /* : void */
{
$this->description = $description;
}
/**
* Get group status.
*
* @return int Group status
*
* @since 1.0.0
*/
public function getStatus() : int
{
return $this->status;
}
/**
* Set group status.
*
* @param int $status Group status
*
* @return void
*
* @throws InvalidEnumValue
*
* @since 1.0.0
*/
public function setStatus(int $status) /* : void */
{
if (!GroupStatus::isValidValue($status)) {
throw new InvalidEnumValue($status);
}
$this->status = $status;
}
/** /**
* Get string representation. * Get string representation.
* *
* @return string * @return string Returns the json_encode of this object
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function __toString() public function __toString() : string
{ {
return json_encode($this->toArray()); return (string) \json_encode($this->toArray());
} }
/** /**
@ -217,11 +115,15 @@ class Group implements ArrayableInterface, \JsonSerializable
/** /**
* Json serialize. * Json serialize.
* *
* @return array * @return array<string, mixed>
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function jsonSerialize()
/**
* {@inheritdoc}
*/
public function jsonSerialize() : mixed
{ {
return $this->toArray(); return $this->toArray();
} }

34
Account/GroupStatus.php Normal file → Executable file
View File

@ -1,32 +1,34 @@
<?php <?php
/** /**
* Orange Management * Jingga
* *
* PHP Version 7.1 * PHP Version 8.2
* *
* @package phpOMS\Account * @package phpOMS\Account
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 1.0 * @license OMS License 2.0
* @version 1.0.0 * @version 1.0.0
* @link http://website.orange-management.de * @link https://jingga.app
*/ */
declare(strict_types = 1); declare(strict_types=1);
namespace phpOMS\Account; namespace phpOMS\Account;
use phpOMS\Stdlib\Base\Enum; use phpOMS\Stdlib\Base\Enum;
/** /**
* Accept status enum. * Group status enum.
* *
* @package phpOMS\Account * @package phpOMS\Account
* @license OMS License 1.0 * @license OMS License 2.0
* @link http://website.orange-management.de * @link https://jingga.app
* @since 1.0.0 * @since 1.0.0
*/ */
abstract class GroupStatus extends Enum abstract class GroupStatus extends Enum
{ {
/* public */ const ACTIVE = 1; public const ACTIVE = 1;
/* public */ const INACTIVE = 2;
/* public */ const HIDDEN = 4; public const INACTIVE = 2;
public const HIDDEN = 4;
} }

45
Account/NullAccount.php Normal file → Executable file
View File

@ -1,27 +1,46 @@
<?php <?php
/** /**
* Orange Management * Jingga
* *
* PHP Version 7.1 * PHP Version 8.2
* *
* @package phpOMS\Account * @package phpOMS\Account
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 1.0 * @license OMS License 2.0
* @version 1.0.0 * @version 1.0.0
* @link http://website.orange-management.de * @link https://jingga.app
*/ */
declare(strict_types = 1); declare(strict_types=1);
namespace phpOMS\Account; namespace phpOMS\Account;
/** /**
* Null account class. * Null account class.
* *
* @package phpOMS\Account * @package phpOMS\Account
* @license OMS License 1.0 * @license OMS License 2.0
* @link http://website.orange-management.de * @link https://jingga.app
* @since 1.0.0 * @since 1.0.0
*/ */
class NullAccount extends Account final class NullAccount extends Account
{ {
/**
* Constructor
*
* @param int $id Model id
*
* @since 1.0.0
*/
public function __construct(int $id = 0)
{
$this->id = $id;
}
/**
* {@inheritdoc}
*/
public function jsonSerialize() : mixed
{
return ['id' => $this->id];
}
} }

46
Account/NullGroup.php Executable file
View File

@ -0,0 +1,46 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Account;
/**
* Null group class.
*
* @package phpOMS\Account
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class NullGroup extends Group
{
/**
* Constructor
*
* @param int $id Model id
*
* @since 1.0.0
*/
public function __construct(int $id = 0)
{
$this->id = $id;
}
/**
* {@inheritdoc}
*/
public function jsonSerialize() : mixed
{
return ['id' => $this->id];
}
}

429
Account/PermissionAbstract.php Normal file → Executable file
View File

@ -1,16 +1,16 @@
<?php <?php
/** /**
* Orange Management * Jingga
* *
* PHP Version 7.1 * PHP Version 8.2
* *
* @package phpOMS\Account * @package phpOMS\Account
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 1.0 * @license OMS License 2.0
* @version 1.0.0 * @version 1.0.0
* @link http://website.orange-management.de * @link https://jingga.app
*/ */
declare(strict_types = 1); declare(strict_types=1);
namespace phpOMS\Account; namespace phpOMS\Account;
@ -20,12 +20,12 @@ namespace phpOMS\Account;
* This permission abstract is the basis for all permissions. Contrary to it's name it is not an * This permission abstract is the basis for all permissions. Contrary to it's name it is not an
* abstract class and can be used directly if needed. * abstract class and can be used directly if needed.
* *
* @package phpOMS\Account * @package phpOMS\Account
* @license OMS License 1.0 * @license OMS License 2.0
* @link http://website.orange-management.de * @link https://jingga.app
* @since 1.0.0 * @since 1.0.0
*/ */
class PermissionAbstract class PermissionAbstract implements \JsonSerializable
{ {
/** /**
* Permission id. * Permission id.
@ -33,276 +33,198 @@ class PermissionAbstract
* @var int * @var int
* @since 1.0.0 * @since 1.0.0
*/ */
protected $id = 0; public int $id = 0;
/** /**
* Unit id. * Unit id.
* *
* @var int * @var null|int
* @since 1.0.0 * @since 1.0.0
*/ */
protected $unit = null; public ?int $unit = null;
/** /**
* App name. * App name.
* *
* @var string * @var null|int
* @since 1.0.0 * @since 1.0.0
*/ */
protected $app = null; public ?int $app = null;
/** /**
* Module id. * Module id.
* *
* @var int * @var null|string
* @since 1.0.0 * @since 1.0.0
*/ */
protected $module = null; public ?string $module = null;
/** /**
* Providing module id. * Providing module id.
* *
* @var int * @var string
* @since 1.0.0 * @since 1.0.0
*/ */
protected $from = 0; public ?string $from = null;
/** /**
* Type. * Type.
* *
* @var int * @var null|int
* @since 1.0.0 * @since 1.0.0
*/ */
protected $type = null; public ?int $category = null;
/** /**
* Element id. * Element id.
* *
* @var int * null === all
* int === specific
*
* @var null|int
* @since 1.0.0 * @since 1.0.0
*/ */
protected $element = null; public ?int $element = null;
/** /**
* Component id. * Component id.
* *
* @var int * null === all
* int === specific
* 0 === own data
*
* @var null|int
* @since 1.0.0 * @since 1.0.0
*/ */
protected $component = null; public ?int $component = null;
/** /**
* Permission. * Permission.
* *
* @var int * @var bool
* @since 1.0.0 * @since 1.0.0
*/ */
protected $permission = PermissionType::NONE; public bool $hasRead = false;
/** /**
* Get permission id. * Permission.
* *
* @return int * @var bool
* * @since 1.0.0
* @since 1.0.0
*/ */
public function getId() : int public bool $hasModify = false;
{
return $this->id;
}
/** /**
* Get unit id. * Permission.
* *
* @return int * @var bool
* * @since 1.0.0
* @since 1.0.0
*/ */
public function getUnit() /* : ?int */ public bool $hasCreate = false;
{
return $this->unit;
}
/** /**
* Set unit id. * Default create permissions
* *
* @param int $unit Unit * @var null|string
* * @since 1.0.0
* @return void
*
* @since 1.0.0
*/ */
public function setUnit(int $unit = null) /* : void */ public ?string $defaultCPermissions = null;
{
$this->unit = $unit;
}
/** /**
* Get app name. * Permission.
* *
* @return string * @var bool
* * @since 1.0.0
* @since 1.0.0
*/ */
public function getApp() /* : ?string */ public bool $hasDelete = false;
{
return $this->app;
}
/** /**
* Set app name. * Permission.
* *
* @param string $app App name * @var bool
* * @since 1.0.0
* @return void
*
* @since 1.0.0
*/ */
public function setApp(string $app = null) /* : void */ public bool $hasPermission = false;
{
$this->app = $app;
}
/** /**
* Get module id. * Default permission permissions
* *
* @return int * @var null|string
* * @since 1.0.0
* @since 1.0.0
*/ */
public function getModule() /* : ?int */ public ?string $defaultPPermissions = null;
{
return $this->module;
}
/** /**
* Set module id. * Constructor.
* *
* @param int $module Module * @param null|int $unit Unit to check (null if all are acceptable)
* @param null|int $app App to check (null if all are acceptable)
* @param null|string $module Module Module to check (null if all are acceptable)
* @param null|string $from Provided by which module
* @param null|int $category Category (e.g. customer) (null if all are acceptable)
* @param null|int $element (e.g. customer id) (null if all are acceptable)
* @param null|int $component (e.g. address) (null if all are acceptable)
* @param int $permission Permission to check
* *
* @return void * @since 1.0.0
*
* @since 1.0.0
*/ */
public function setModule(int $module = null) /* : void */ public function __construct(
{ ?int $unit = null,
$this->module = $module; ?int $app = null,
} ?string $module = null,
?string $from = null,
/** ?int $category = null,
* Get providing module id. ?int $element = null,
* ?int $component = null,
* @return int int $permission = PermissionType::NONE
* ) {
* @since 1.0.0 $this->unit = $unit;
*/ $this->app = $app;
public function getFrom() /* : ?int */ $this->module = $module;
{ $this->from = $from;
return $this->from; $this->category = $category;
} $this->element = $element;
/**
* Set providing module id.
*
* @param int $from Providing module
*
* @return void
*
* @since 1.0.0
*/
public function setFrom(int $from = null) /* : void */
{
$this->from = $from;
}
/**
* Get type.
*
* @return int
*
* @since 1.0.0
*/
public function getType() /* : ?int */
{
return $this->type;
}
/**
* Set type.
*
* @param int $type Type
*
* @return void
*
* @since 1.0.0
*/
public function setType(int $type = null) /* : void */
{
$this->type = $type;
}
/**
* Get element id.
*
* @return int
*
* @since 1.0.0
*/
public function getElement() /* : ?int */
{
return $this->element;
}
/**
* Set element id.
*
* @param int $element Element id
*
* @return void
*
* @since 1.0.0
*/
public function setElement(int $element = null) /* : void */
{
$this->element = $element;
}
/**
* Get component id.
*
* @return int
*
* @since 1.0.0
*/
public function getComponent() /* : ?int */
{
return $this->component;
}
/**
* Set component id.
*
* @param int $component Component
*
* @return void
*
* @since 1.0.0
*/
public function setComponent(int $component = null) /* : void */
{
$this->component = $component; $this->component = $component;
$this->hasRead = ($permission & PermissionType::READ) === PermissionType::READ;
$this->hasCreate = ($permission & PermissionType::CREATE) === PermissionType::CREATE;
$this->hasModify = ($permission & PermissionType::MODIFY) === PermissionType::MODIFY;
$this->hasDelete = ($permission & PermissionType::DELETE) === PermissionType::DELETE;
$this->hasPermission = ($permission & PermissionType::PERMISSION) === PermissionType::PERMISSION;
} }
/** /**
* Get permission * Get permission
* *
* @return int * @return int Returns the permission (PermissionType)
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function getPermission() : int public function getPermission() : int
{ {
return $this->permission; $permission = 0;
if ($this->hasRead) {
$permission |= PermissionType::READ;
}
if ($this->hasCreate) {
$permission |= PermissionType::CREATE;
}
if ($this->hasModify) {
$permission |= PermissionType::MODIFY;
}
if ($this->hasDelete) {
$permission |= PermissionType::DELETE;
}
if ($this->hasPermission) {
$permission |= PermissionType::PERMISSION;
}
return $permission === 0 ? PermissionType::NONE : $permission;
} }
/** /**
@ -312,11 +234,15 @@ class PermissionAbstract
* *
* @return void * @return void
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function setPermission(int $permission = 0) /* : void */ public function setPermission(int $permission = 0) : void
{ {
$this->permission = $permission; $this->hasRead = ($permission & PermissionType::READ) === PermissionType::READ;
$this->hasCreate = ($permission & PermissionType::CREATE) === PermissionType::CREATE;
$this->hasModify = ($permission & PermissionType::MODIFY) === PermissionType::MODIFY;
$this->hasDelete = ($permission & PermissionType::DELETE) === PermissionType::DELETE;
$this->hasPermission = ($permission & PermissionType::PERMISSION) === PermissionType::PERMISSION;
} }
/** /**
@ -326,11 +252,27 @@ class PermissionAbstract
* *
* @return void * @return void
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function addPermission(int $permission = 0) /* : void */ public function addPermission(int $permission = 0) : void
{ {
$this->permission |= $permission; switch($permission) {
case PermissionType::READ:
$this->hasRead = true;
break;
case PermissionType::CREATE:
$this->hasCreate = true;
break;
case PermissionType::MODIFY:
$this->hasModify = true;
break;
case PermissionType::DELETE:
$this->hasDelete = true;
break;
case PermissionType::PERMISSION:
$this->hasPermission = true;
break;
}
} }
/** /**
@ -338,12 +280,87 @@ class PermissionAbstract
* *
* @param int $permission Permission * @param int $permission Permission
* *
* @return bool * @return bool Returns true if the permission is set otherwise returns false
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function hasPermission(int $permission) : bool public function hasPermissionFlags(int $permission) : bool
{ {
return ($this->permission | $permission) === $this->permission; return ($this->getPermission() & $permission) === $permission;
}
/**
* Has permissions.
*
* Checks if the permission is defined
*
* @param int $permission Permission to check
* @param null|int $unit Unit Unit to check (null if all are acceptable)
* @param null|int $app App App to check (null if all are acceptable)
* @param null|string $module Module Module to check (null if all are acceptable)
* @param null|int $category Category (e.g. customer) (null if all are acceptable)
* @param null|int $element (e.g. customer id) (null if all are acceptable)
* @param null|int $component (e.g. address) (null if all are acceptable)
*
* @return bool Returns true if the permission is set, false otherwise
*
* @since 1.0.0
*/
public function hasPermission(
int $permission,
?int $unit = null,
?int $app = null,
?string $module = null,
?int $category = null,
?int $element = null,
?int $component = null
) : bool
{
return $permission === PermissionType::NONE ||
(($unit === null || $this->unit === null || $this->unit === $unit)
&& ($app === null || $this->app === null || $this->app === $app)
&& ($module === null || $this->module === null || $this->module === $module)
&& ($category === null || $this->category === null || $this->category === $category)
&& ($element === null || $this->element === null || $this->element === $element)
&& ($component === null || $this->component === null || $this->component === $component)
&& ($this->getPermission() & $permission) === $permission);
}
/**
* Is equals.
*
* @param self $permission Permission
*
* @return bool Returns true if the permission is the same
*
* @since 1.0.0
*/
public function isEqual(self $permission) : bool
{
return $this->unit === $permission->unit
&& $this->app === $permission->app
&& $this->module === $permission->module
&& $this->category === $permission->category
&& $this->element === $permission->element
&& $this->component === $permission->component
&& $this->getPermission() === $permission->getPermission();
}
/**
* {@inheritdoc}
*/
public function jsonSerialize() : mixed
{
return [
'id' => $this->id,
'unit' => $this->unit,
'app' => $this->app,
'module' => $this->module,
'from' => $this->from,
'category' => $this->category,
'element' => $this->element,
'component' => $this->component,
'permission' => $this->getPermission(),
];
} }
} }

View File

@ -0,0 +1,154 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Account;
/**
* Permission handling trait.
*
* @package phpOMS\Account
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
trait PermissionHandlingTrait
{
/**
* Permissions.
*
* @var PermissionAbstract[]
* @since 1.0.0
*/
public array $permissions = [];
/**
* Set permissions.
*
* The method accepts an array of permissions. All existing permissions are replaced.
*
* @param PermissionAbstract[] $permissions Permissions
*
* @return void
*
* @since 1.0.0
*/
public function setPermissions(array $permissions) : void
{
$this->permissions = $permissions;
}
/**
* Add permissions.
*
* Adds permissions
*
* @param array<array|PermissionAbstract> $permissions Array of permissions to add
*
* @return void
*
* @since 1.0.0
*/
public function addPermissions(array $permissions) : void
{
foreach ($permissions as $permission) {
if (\is_array($permission)) {
$this->permissions = \array_merge($this->permissions, $permission);
} else {
$this->permissions[] = $permission;
}
}
}
/**
* Add permission.
*
* Adds a single permission
*
* @param PermissionAbstract $permission Permission to add
*
* @return void
*
* @since 1.0.0
*/
public function addPermission(PermissionAbstract $permission) : void
{
$this->permissions[] = $permission;
}
/**
* Remove permission.
*
* @param PermissionAbstract $permission Permission to remove
*
* @return void
*
* @since 1.0.0
*/
public function removePermission(PermissionAbstract $permission) : void
{
foreach ($this->permissions as $key => $p) {
if ($p->isEqual($permission)) {
unset($this->permissions[$key]);
}
}
}
/**
* Get permissions.
*
* @return PermissionAbstract[]
*
* @since 1.0.0
*/
public function getPermissions() : array
{
return $this->permissions;
}
/**
* Has permissions.
*
* Checks if the permission is defined
*
* @param int $permission Permission to check
* @param null|int $unit Unit Unit to check (null if all are acceptable)
* @param null|int $app App App to check (null if all are acceptable)
* @param null|string $module Module Module to check (null if all are acceptable)
* @param null|int $category Type (e.g. customer) (null if all are acceptable)
* @param null|int $element (e.g. customer id) (null if all are acceptable)
* @param null|int $component (e.g. address) (null if all are acceptable)
*
* @return bool Returns true if the permission is set, false otherwise
*
* @since 1.0.0
*/
public function hasPermission(
int $permission,
?int $unit = null,
?int $app = null,
?string $module = null,
?int $category = null,
?int $element = null,
?int $component = null
) : bool
{
foreach ($this->permissions as $p) {
if ($p->hasPermission($permission, $unit, $app, $module, $category, $element, $component)) {
return true;
}
}
return false;
}
}

34
Account/PermissionOwner.php Executable file
View File

@ -0,0 +1,34 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Account
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Account;
use phpOMS\Stdlib\Base\Enum;
/**
* Permision type/owner enum.
*
* A permission can be long to a group or an account.
*
* @package phpOMS\Account
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
abstract class PermissionOwner extends Enum
{
public const GROUP = 1;
public const ACCOUNT = 2;
}

41
Account/PermissionType.php Normal file → Executable file
View File

@ -1,16 +1,16 @@
<?php <?php
/** /**
* Orange Management * Jingga
* *
* PHP Version 7.1 * PHP Version 8.2
* *
* @package phpOMS\Account * @package phpOMS\Account
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 1.0 * @license OMS License 2.0
* @version 1.0.0 * @version 1.0.0
* @link http://website.orange-management.de * @link https://jingga.app
*/ */
declare(strict_types = 1); declare(strict_types=1);
namespace phpOMS\Account; namespace phpOMS\Account;
@ -19,17 +19,22 @@ use phpOMS\Stdlib\Base\Enum;
/** /**
* Permission type enum. * Permission type enum.
* *
* @package phpOMS\Account * @package phpOMS\Account
* @license OMS License 1.0 * @license OMS License 2.0
* @link http://website.orange-management.de * @link https://jingga.app
* @since 1.0.0 * @since 1.0.0
*/ */
abstract class PermissionType extends Enum abstract class PermissionType extends Enum
{ {
/* public */ const NONE = 1; public const NONE = 1; // No permission
/* public */ const READ = 2;
/* public */ const CREATE = 4; public const READ = 2; // Is able to read models/data
/* public */ const MODIFY = 8;
/* public */ const DELETE = 16; public const CREATE = 4; // Is able to create models/data
/* public */ const PERMISSION = 32;
public const MODIFY = 8; // Is able to modify models/data
public const DELETE = 16; // Is able to delete models/data
public const PERMISSION = 32; // Is able to change permissions
} }

102
Ai/NeuralNetwork/Neuron.php Executable file
View File

@ -0,0 +1,102 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Ai\NeuralNetwork
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Ai\NeuralNetwork;
/**
* Neuron
*
* @package phpOMS\Ai\NeuralNetwork
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class Neuron
{
/**
* Neuron inputs
*
* @var array
* @since 1.0.0
*/
private array $inputs = [];
/**
* Input weights
*
* @var array
* @since 1.0.0
*/
private array $weights = [];
/**
* Bias
*
* @var float
* @since 1.0.0
*/
public float $bias = 0;
/**
* Constructor.
*
* @param array $inputs Neuron inputs/connections
* @param array $weights Input weights
* @param float $bias Input bias
*
* @since 1.0.0
*/
public function __construct(array $inputs = [], array $weights = [], float $bias = 0.0)
{
$this->inputs = $inputs;
$this->weights = $weights;
$this->bias = $bias;
}
/**
* Add neuron input
*
* @param mixed $input Input
* @param float $weight Weight of input
*
* @return void
*
* @since 1.0.0
*/
public function addInput(mixed $input, float $weight) : void
{
$this->inputs[] = $input;
$this->weights[] = $weight;
}
/**
* Create node output
*
* @return float
*
* @since 1.0.0
*/
public function output() : float
{
$length = \count($this->inputs);
$output = 0.0;
for ($i = 0; $i < $length; ++$i) {
$output += $this->inputs[$i]->output() * $this->weights[$i];
}
return $output + $this->bias;
// return $this->activationFunction($output + $this->bias);
}
}

363
Ai/Ocr/BasicOcr.php Executable file
View File

@ -0,0 +1,363 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Ai\Ocr
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Ai\Ocr;
use phpOMS\Math\Topology\MetricsND;
use phpOMS\System\File\PathException;
/**
* Basic OCR implementation for MNIST data
*
* @package phpOMS\Ai\Ocr
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class BasicOcr
{
/**
* Dataset on which the OCR is trained on.
*
* The data needs to be MNIST data.
*
* @var array
* @since 1.0.0
*/
private array $Xtrain = [];
/**
* Resultset on which the OCR is trained on.
*
* These are the actual values for the Xtrain data and must therefore have the same dimension.
*
* The labels need to be MNIST labels.
*
* @var array
* @since 1.0.0
*/
private array $ytrain = [];
/**
* Train OCR with data and result/labels
*
* @param string $dataPath Impage path to read
* @param string $labelPath Label path to read
* @param int $limit Limit (0 = unlimited)
*
* @return void
*
* @since 1.0.0
*/
public function trainWith(string $dataPath, string $labelPath, int $limit = 0) : void
{
$Xtrain = $this->readImages($dataPath, $limit);
$ytrain = $this->readLabels($labelPath, $limit);
$this->Xtrain = \array_merge($this->Xtrain, $Xtrain);
$this->ytrain = \array_merge($this->ytrain, $ytrain);
}
/**
* Read image from path
*
* @param string $path Image to read
* @param int $limit Limit
*
* @return array
*
* @throws PathException
*
* @since 1.0.0
*/
private function readImages(string $path, int $limit = 0) : array
{
if (!\is_file($path)) {
throw new PathException($path);
}
$fp = \fopen($path, 'r');
if ($fp === false) {
throw new PathException($path); // @codeCoverageIgnore
}
if (($read = \fread($fp, 4)) === false || ($unpack = \unpack('N', $read)) === false) {
return []; // @codeCoverageIgnore
}
// $magicNumber = $unpack[1];
// 2051 === image data (should always be this)
// 2049 === label data
if (($read = \fread($fp, 4)) === false || ($unpack = \unpack('N', $read)) === false) {
return []; // @codeCoverageIgnore
}
$numberOfImages = $unpack[1];
if ($limit > 0) {
$numberOfImages = \min($numberOfImages, $limit);
}
if (($read = \fread($fp, 4)) === false || ($unpack = \unpack('N', $read)) === false) {
return []; // @codeCoverageIgnore
}
/** @var int<0, max> $numberOfRows */
$numberOfRows = (int) $unpack[1];
if (($read = \fread($fp, 4)) === false || ($unpack = \unpack('N', $read)) === false) {
return []; // @codeCoverageIgnore
}
/** @var int<0, max> $numberOfColumns */
$numberOfColumns = (int) $unpack[1];
$images = [];
for ($i = 0; $i < $numberOfImages; ++$i) {
if (($read = \fread($fp, $numberOfRows * $numberOfColumns)) === false
|| ($unpack = \unpack('C*', $read)) === false
) {
return []; // @codeCoverageIgnore
}
$images[] = \array_values($unpack);
}
\fclose($fp);
return $images;
}
/**
* Read labels from from path
*
* @param string $path Labels path
* @param int $limit Limit
*
* @return array
*
* @throws PathException
*
* @since 1.0.0
*/
private function readLabels(string $path, int $limit = 0) : array
{
if (!\is_file($path)) {
throw new PathException($path);
}
$fp = \fopen($path, 'r');
if ($fp === false) {
throw new PathException($path); // @codeCoverageIgnore
}
if (($read = \fread($fp, 4)) === false || ($unpack = \unpack('N', $read)) === false) {
return []; // @codeCoverageIgnore
}
// $magicNumber = $unpack[1];
// 2051 === image data
// 2049 === label data (should always be this)
if (($read = \fread($fp, 4)) === false || ($unpack = \unpack('N', $read)) === false) {
return []; // @codeCoverageIgnore
}
$numberOfLabels = $unpack[1];
if ($limit > 0) {
$numberOfLabels = \min($numberOfLabels, $limit);
}
$labels = [];
for ($i = 0; $i < $numberOfLabels; ++$i) {
if (($read = \fread($fp, 1)) === false || ($unpack = \unpack('C', $read)) === false) {
return []; // @codeCoverageIgnore
}
$labels[] = $unpack[1];
}
\fclose($fp);
return $labels;
}
/**
* Find the k-nearest matches for test data
*
* @param array $Xtrain Image data used for training
* @param array $ytrain Labels associated with the trained data
* @param array $Xtest Image data from the image to categorize
* @param int $k Amount of best fits that should be found
*/
private function kNearest(array $Xtrain, array $ytrain, array $Xtest, int $k = 3) : array
{
$predictedLabels = [];
foreach ($Xtest as $sample) {
$distances = $this->getDistances($Xtrain, $sample);
\asort($distances);
$keys = \array_keys($distances);
$candidateLabels = [];
for ($i = 0; $i < $k; ++$i) {
$candidateLabels[] = $ytrain[$keys[$i]];
}
// find best match
$countedCandidates = \array_count_values($candidateLabels);
foreach ($candidateLabels as $i => $label) {
$predictedLabels[] = [
'label' => $label,
'prob' => $countedCandidates[$label] / $k,
];
}
}
return $predictedLabels;
}
/**
* Fitting method in order to see how similar two datasets are.
*
* @param array $Xtrain Image data used for training
* @param array $sample Image data to compare against
*
* @return array
*
* @since 1.0.0
*/
private function getDistances(array $Xtrain, array $sample) : array
{
$dist = [];
foreach ($Xtrain as $train) {
$dist[] = MetricsND::euclidean($train, $sample);
}
return $dist;
}
/**
* Create MNIST file from images
*
* @param string[] $images Images
* @param string $out Output file
* @param int $resolution Resolution of the iomages
*
* @return void
*
* @since 1.0.0
*/
public static function imagesToMNIST(array $images, string $out, int $resolution) : void
{
$out = \fopen($out, 'wb');
if ($out === false) {
return; // @codeCoverageIgnore
}
\fwrite($out, \pack('N', 2051));
\fwrite($out, \pack('N', \count($images)));
\fwrite($out, \pack('N', $resolution));
\fwrite($out, \pack('N', $resolution));
$size = $resolution * $resolution;
foreach ($images as $in) {
$inString = \file_get_contents($in);
if ($inString === false) {
continue;
}
$im = \imagecreatefromstring($inString);
if ($im === false) {
continue;
}
$new = \imagescale($im, $resolution, $resolution);
if ($new === false) {
continue;
}
// Convert the image to grayscale and normalize the pixel values
$mnist = [];
for ($i = 0; $i < $resolution; ++$i) {
for ($j = 0; $j < $resolution; ++$j) {
$pixel = \imagecolorat($new, $j, $i);
$gray = \round(
(
0.299 * (($pixel >> 16) & 0xFF)
+ 0.587 * (($pixel >> 8) & 0xFF)
+ 0.114 * ($pixel & 0xFF)
) / 255,
3
);
$mnist[] = $gray;
}
}
for ($i = 0; $i < $size; ++$i) {
\fwrite($out, \pack('C', (int) \round($mnist[$i] * 255)));
}
}
\fclose($out);
}
/**
* Convert labels to MNIST format
*
* @param string[] $data Labels (one char per label)
* @param string $out Output path
*
* @return void
*
* @since 1.0.0
*/
public static function labelsToMNIST(array $data, string $out) : void
{
// Only allows single char labels
$out = \fopen($out, 'wb');
if ($out === false) {
return; // @codeCoverageIgnore
}
\fwrite($out, \pack('N', 2049));
\fwrite($out, \pack('N', \count($data)));
foreach ($data as $e) {
\fwrite($out, \pack('C', $e));
}
\fclose($out);
}
/**
* Categorize an unknown image
*
* @param string $path Path to the image to categorize/evaluate/match against the training data
* @param int $comparison Amount of comparisons
* @param int $limit Limit (0 = unlimited)
*
* @return array
*
* @since 1.0.0
*/
public function matchImage(string $path, int $comparison = 3, int $limit = 0) : array
{
$Xtest = $this->readImages($path, $limit);
return $this->kNearest($this->Xtrain, $this->ytrain, $Xtest, $comparison);
}
}

159
Ai/Ocr/Tesseract/TesseractOcr.php Executable file
View File

@ -0,0 +1,159 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Ai\Ocr\Tesseract
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Ai\Ocr\Tesseract;
use phpOMS\System\File\PathException;
use phpOMS\System\SystemUtils;
/**
* Tesseract api
*
* @package phpOMS\Ai\Ocr\Tesseract
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class TesseractOcr
{
/**
* Tesseract path.
*
* @var string
* @since 1.0.0
*/
protected static string $bin = '/usr/bin/tesseract';
/**
* Set tesseract binary.
*
* @param string $path tesseract path
*
* @return void
*
* @throws PathException This exception is thrown if the binary path doesn't exist
*
* @since 1.0.0
*/
public static function setBin(string $path) : void
{
if (\realpath($path) === false) {
throw new PathException($path);
}
self::$bin = \realpath($path);
}
/**
* Prase image
*
* @param string $image Image path
* @param array $languages Languages to use
* @param int $psm Page segmentation mode (0 - 13)
* 0 Orientation and script detection (OSD) only.
* 1 Automatic page segmentation with OSD.
* 2 Automatic page segmentation, but no OSD, or OCR.
* 3 Fully automatic page segmentation, but no OSD. (Default)
* 4 Assume a single column of text of variable sizes.
* 5 Assume a single uniform block of vertically aligned text.
* 6 Assume a single uniform block of text.
* 7 Treat the image as a single text line.
* 8 Treat the image as a single word.
* 9 Treat the image as a single word in a circle.
* 10 Treat the image as a single character.
* 11 Sparse text. Find as much text as possible in no particular order.
* 12 Sparse text with OSD.
* 13 Raw line. Treat the image as a single text line, bypassing hacks that are Tesseract-specific.
* @param int $oem OCR engine modes
* 0 Legacy engine only.
* 1 Neural nets LSTM engine only.
* 2 Legacy + LSTM engines.
* 3 Default, based on what is available
*
* @return string
*
* @since 1.0.0
*/
public function parseImage(string $image, array $languages = ['eng', 'deu'], int $psm = 3, int $oem = 3) : string
{
$temp = \tempnam(\sys_get_temp_dir(), 'oms_ocr_');
if ($temp === false) {
return '';
}
$extension = 'png';
try {
// Tesseract needs higher dpi to work properly (identify + adjust if necessary)
$dpi = (int) \trim(\implode('', SystemUtils::runProc(
'identify',
'-quiet -format "%x" ' . $image
)));
if ($dpi < 300) {
$split = \explode('.', $image);
$extension = \end($split);
SystemUtils::runProc(
'convert',
'-units PixelsPerInch ' . $image . ' -resample 300 ' . $temp . '.' . $extension
);
$image = $temp . '.' . $extension;
}
// Do actual parsing
SystemUtils::runProc(
self::$bin,
$image . ' '
. $temp
. ' -c preserve_interword_spaces=1'
. ' --psm ' . $psm
. ' --oem ' . $oem
. (empty($languages) ? '' : ' -l ' . \implode('+', $languages))
);
} catch (\Throwable $_) {
if (\is_file($temp . '.' . $extension)) {
\unlink($temp . '.' . $extension);
}
return '';
}
if (\is_file($temp . '.' . $extension)) {
\unlink($temp . '.' . $extension);
}
$filepath = \is_file($temp . '.txt')
? $temp . '.txt'
: $temp;
if (!\is_file($filepath)) {
// @codeCoverageIgnoreStart
\unlink($temp);
return '';
// @codeCoverageIgnoreEnd
}
$parsed = \file_get_contents($filepath);
if ($parsed === false) {
$parsed = '';
}
\unlink($filepath);
\unlink($temp);
return \trim($parsed);
}
}

View File

@ -0,0 +1,30 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
/**
* Clustering points
*
* @package phpOMS\Algorithm\Clustering
* @license OMS License 2.0
* @link https://jingga.app
* @see ./clustering_overview.png
* @since 1.0.0
*
* @todo Implement
*/
final class AffinityPropagation
{
}

View File

@ -0,0 +1,154 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
use phpOMS\Math\Topology\MetricsND;
/**
* Clustering points
*
* The parent category of this clustering algorithm is hierarchical clustering.
*
* @package phpOMS\Algorithm\Clustering
* @license Base: MIT Copyright (c) 2020 Greene Laboratory
* @license OMS License 2.0
* @link https://jingga.app
* @see ./DivisiveClustering.php
* @see ./clustering_overview.png
* @see https://en.wikipedia.org/wiki/Hierarchical_clustering
* @see https://github.com/greenelab/hclust/blob/master/README.md
* @since 1.0.0
*
* @todo Implement
* @todo Implement missing linkage functions
*/
final class AgglomerativeClustering implements ClusteringInterface
{
/**
* Metric to calculate the distance between two points
*
* @var \Closure
* @since 1.0.0
*/
public \Closure $metric;
/**
* Metric to calculate the distance between two points
*
* @var \Closure
* @since 1.0.0
*/
public \Closure $linkage;
/**
* Constructor
*
* @param null|\Closure $metric metric to use for the distance between two points
*
* @since 1.0.0
*/
public function __construct(?\Closure $metric = null, ?\Closure $linkage = null)
{
$this->metric = $metric ?? function (Point $a, Point $b) {
$aCoordinates = $a->coordinates;
$bCoordinates = $b->coordinates;
return MetricsND::euclidean($aCoordinates, $bCoordinates);
};
$this->linkage = $linkage ?? function (array $a, array $b, array $distances) {
return self::averageDistanceLinkage($a, $b, $distances);
};
}
/**
* Maximum/Complete-Linkage clustering
*/
public static function maximumDistanceLinkage(array $setA, array $setB, array $distances) : float
{
$max = \PHP_INT_MIN;
foreach ($setA as $a) {
foreach ($setB as $b) {
if ($distances[$a][$b] > $max) {
$max = $distances[$a][$b];
}
}
}
return $max;
}
/**
* Minimum/Single-Linkage clustering
*/
public static function minimumDistanceLinkage(array $setA, array $setB, array $distances) : float
{
$min = \PHP_INT_MAX;
foreach ($setA as $a) {
foreach ($setB as $b) {
if ($distances[$a][$b] < $min) {
$min = $distances[$a][$b];
}
}
}
return $min;
}
/**
* Unweighted average linkage clustering (UPGMA)
*/
public static function averageDistanceLinkage(array $setA, array $setB, array $distances) : float
{
$distance = 0;
foreach ($setA as $a) {
$distance += \array_sum($distances[$a]);
}
return $distance / \count($setA) / \count($setB);
}
/**
* {@inheritdoc}
*/
public function getCentroids() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function getClusters() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function cluster(Point $point) : ?Point
{
return null;
}
/**
* {@inheritdoc}
*/
public function getNoise() : array
{
return [];
}
}

View File

@ -0,0 +1,61 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
/**
* Clustering points
*
* @package phpOMS\Algorithm\Clustering
* @license OMS License 2.0
* @link https://jingga.app
* @see ./clustering_overview.png
* @since 1.0.0
*
* @todo Implement
*/
final class Birch implements ClusteringInterface
{
/**
* {@inheritdoc}
*/
public function getCentroids() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function getClusters() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function cluster(Point $point) : ?Point
{
return null;
}
/**
* {@inheritdoc}
*/
public function getNoise() : array
{
return [];
}
}

View File

@ -0,0 +1,71 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
/**
* Clustering interface.
*
* @package phpOMS\Algorithm\Clustering;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
interface ClusteringInterface
{
/**
* Get cluster centroids
*
* @return Point[]
*
* @since 1.0.0
*/
public function getCentroids() : array;
/**
* Get cluster assignments of the training data
*
* @return Point[]
*
* @since 1.0.0
*/
public function getClusters() : array;
/**
* Cluster a single point
*
* This point doesn't have to be in the training data.
*
* @param Point $point Point to cluster
*
* @return null|Point
*
* @since 1.0.0
*/
public function cluster(Point $point) : ?Point;
/**
* Get noise data.
*
* Data points from the training data that are not part of a cluster.
*
* @return Point[]
*
* @since 1.0.0
*/
public function getNoise() : array;
// Not possible to interface due to different implementations
// public function generateClusters(...) : void
}

View File

@ -0,0 +1,331 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
use phpOMS\Math\Geometry\ConvexHull\MonotoneChain;
use phpOMS\Math\Geometry\Shape\D2\Polygon;
use phpOMS\Math\Topology\MetricsND;
/**
* Clustering points
*
* @package phpOMS\Algorithm\Clustering
* @license OMS License 2.0
* @link https://jingga.app
* @see ./clustering_overview.png
* @since 1.0.0
*
* @todo Expand to n dimensions
*/
final class DBSCAN implements ClusteringInterface
{
/**
* Epsilon for float comparison.
*
* @var float
* @since 1.0.0
*/
public const EPSILON = 4.88e-04;
/**
* Metric to calculate the distance between two points
*
* @var \Closure
* @since 1.0.0
*/
private \Closure $metric;
/**
* Points outside of any cluster
*
* @var Point[]
* @since 1.0.0
*/
private array $noisePoints = [];
/**
* All points
*
* @var Point[]
* @since 1.0.0
*/
private array $points = [];
/**
* Points of the cluster centers
*
* @var Point[]
* @since 1.0.0
*/
private array $clusterCenters = [];
/**
* Clusters
*
* Array of points assigned to a cluster
*
* @var array<int, Point[]>
* @since 1.0.0
*/
private array $clusters = [];
/**
* Convex hull of all clusters
*
* @var array<array>
* @since 1.0.0
*/
private array $convexHulls = [];
/**
* Cluster points
*
* Points in clusters (helper to avoid looping the cluster array)
*
* @var array
* @since 1.0.0
*/
private array $clusteredPoints = [];
/**
* Distance matrix
*
* Distances between points
*
* @var array<float[]>
* @since 1.0.0
*/
private array $distanceMatrix = [];
/**
* Constructor
*
* @param null|\Closure $metric metric to use for the distance between two points
*
* @since 1.0.0
*/
public function __construct(?\Closure $metric = null)
{
$this->metric = $metric ?? function (Point $a, Point $b) {
$aCoordinates = $a->coordinates;
$bCoordinates = $b->coordinates;
return MetricsND::euclidean($aCoordinates, $bCoordinates);
};
}
/**
* Expand cluster with additional point and potential neighbors.
*
* @param Point $point Point to add to a cluster
* @param array $neighbors Neighbors of point
* @param int $c Cluster id
* @param float $epsilon Max distance
* @param int $minPoints Min amount of points required for a cluster
*
* @return void
*
* @since 1.0.0
*/
private function expandCluster(
Point $point,
array $neighbors,
int $c,
float $epsilon,
int $minPoints
) : void
{
$this->clusters[$c][] = $point;
$this->clusteredPoints[] = $point;
$nPoint = \reset($neighbors);
while ($nPoint) {
$neighbors2 = $this->findNeighbors($nPoint, $epsilon);
if (\count($neighbors2) >= $minPoints) {
foreach ($neighbors2 as $nPoint2) {
if (!isset($neighbors[$nPoint2->name])) {
$neighbors[$nPoint2->name] = $nPoint2;
}
}
}
if (!\in_array($nPoint->name, $this->clusteredPoints)) {
$this->clusters[$c][] = $nPoint;
$this->clusteredPoints[] = $nPoint;
}
$nPoint = \next($neighbors);
}
}
/**
* Find neighbors of a point
*
* @param Point $point Base point for potential neighbors
* @param float $epsilon Max distance to neighbor
*
* @return array
*
* @since 1.0.0
*/
private function findNeighbors(Point $point, float $epsilon) : array
{
$neighbors = [];
foreach ($this->points as $point2) {
if ($point->isEquals($point2)) {
$distance = isset($this->distanceMatrix[$point->name])
? $this->distanceMatrix[$point->name][$point2->name]
: $this->distanceMatrix[$point2->name][$point->name];
if ($distance < $epsilon) {
$neighbors[$point2->name] = $point2;
}
}
}
return $neighbors;
}
/**
* Generate distances between points
*
* @param array $points Array of all points
*
* @return float[]
*
* @since 1.0.0
*/
private function generateDistanceMatrix(array $points) : array
{
$distances = [];
foreach ($points as $point) {
$distances[$point->name] = [];
foreach ($points as $point2) {
$distances[$point->name][$point2->name] = ($this->metric)($point, $point2);
}
}
/** @var float[] $distances */
return $distances;
}
/**
* {@inheritdoc}
*/
public function cluster(Point $point) : ?Point
{
if ($this->convexHulls === []) {
foreach ($this->clusters as $c => $cluster) {
$points = [];
foreach ($cluster as $p) {
$points[] = $p->coordinates;
}
// @todo this is only good for 2D. Fix this for ND.
$this->convexHulls[$c] = MonotoneChain::createConvexHull($points);
}
}
foreach ($this->convexHulls as $c => $hull) {
if (Polygon::isPointInPolygon($point->coordinates, $hull) <= 0) {
return $hull;
}
}
return null;
}
/**
* Generate the clusters of the points
*
* @param Point[] $points Points to cluster
* @param float $epsilon Max distance
* @param int $minPoints Min amount of points required for a cluster
*
* @return void
*
* @since 1.0.0
*/
public function generateClusters(array $points, float $epsilon, int $minPoints) : void
{
$this->noisePoints = [];
$this->clusters = [];
$this->clusteredPoints = [];
$this->points = $points;
$this->convexHulls = [];
$this->distanceMatrix = $this->generateDistanceMatrix($points);
$c = 0;
$this->clusters[$c] = [];
foreach ($this->points as $point) {
$neighbors = $this->findNeighbors($point, $epsilon);
if (\count($neighbors) < $minPoints) {
$this->noisePoints[] = $point->name;
} elseif (!\in_array($point->name, $this->clusteredPoints)) {
$this->expandCluster($point, $neighbors, $c, $epsilon, $minPoints);
++$c;
$this->clusters[$c] = [];
}
}
}
/**
* {@inheritdoc}
*/
public function getCentroids() : array
{
if (!empty($this->clusterCenters)) {
return $this->clusterCenters;
}
$dim = \count(\reset($this->points)->getCoordinates());
foreach ($this->clusters as $cluster) {
$middle = \array_fill(0, $dim, 0);
foreach ($cluster as $point) {
for ($i = 0; $i < $dim; ++$i) {
$middle[$i] += $point->getCoordinate($i);
}
}
for ($i = 0; $i < $dim; ++$i) {
$middle[$i] /= \count($cluster);
}
$this->clusterCenters = new Point($middle);
}
return $this->clusterCenters;
}
/**
* {@inheritdoc}
*/
public function getNoise() : array
{
return $this->noisePoints;
}
/**
* {@inheritdoc}
*/
public function getClusters() : array
{
return $this->clusters;
}
}

View File

@ -0,0 +1,65 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
/**
* Clustering points
*
* The parent category of this clustering algorithm is hierarchical clustering.
*
* @package phpOMS\Algorithm\Clustering
* @license OMS License 2.0
* @link https://jingga.app
* @see ./AgglomerativeClustering.php
* @see ./clustering_overview.png
* @see https://en.wikipedia.org/wiki/Hierarchical_clustering
* @since 1.0.0
*
* @todo Implement
*/
final class DivisiveClustering implements ClusteringInterface
{
/**
* {@inheritdoc}
*/
public function getCentroids() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function getClusters() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function cluster(Point $point) : ?Point
{
return null;
}
/**
* {@inheritdoc}
*/
public function getNoise() : array
{
return [];
}
}

278
Algorithm/Clustering/Kmeans.php Executable file
View File

@ -0,0 +1,278 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
use phpOMS\Math\Topology\MetricsND;
/**
* Clustering points
*
* @package phpOMS\Algorithm\Clustering
* @license OMS License 2.0
* @link https://jingga.app
* @see ./clustering_overview.png
* @since 1.0.0
*/
final class Kmeans implements ClusteringInterface
{
/**
* Epsilon for float comparison.
*
* @var float
* @since 1.0.0
*/
public const EPSILON = 4.88e-04;
/**
* Metric to calculate the distance between two points
*
* @var \Closure
* @since 1.0.0
*/
private \Closure $metric;
/**
* Points of the cluster centers
*
* @var Point[]
* @since 1.0.0
*/
private array $clusterCenters = [];
/**
* Points of the clusters
*
* @var Point[]
* @since 1.0.0
*/
private array $clusters = [];
/**
* Points
*
* @var Point[]
* @since 1.0.0
*/
private array $points = [];
/**
* Constructor
*
* @param null|\Closure $metric metric to use for the distance between two points
*
* @since 1.0.0
*/
public function __construct(?\Closure $metric = null)
{
$this->metric = $metric ?? function (Point $a, Point $b) {
$aCoordinates = $a->coordinates;
$bCoordinates = $b->coordinates;
return MetricsND::euclidean($aCoordinates, $bCoordinates);
};
}
/**
* {@inheritdoc}
*/
public function cluster(Point $point) : ?Point
{
$bestCluster = null;
$bestDistance = \PHP_FLOAT_MAX;
foreach ($this->clusterCenters as $center) {
if (($distance = ($this->metric)($center, $point)) < $bestDistance) {
$bestCluster = $center;
$bestDistance = $distance;
}
}
return $bestCluster;
}
/**
* {@inheritdoc}
*/
public function getCentroids() : array
{
return $this->clusterCenters;
}
/**
* {@inheritdoc}
*/
public function getNoise() : array
{
return [];
}
/**
* Generate the clusters of the points
*
* @param Point[] $points Points to cluster
* @param int<1, max> $clusters Amount of clusters
*
* @return void
*
* @since 1.0.0
*/
public function generateClusters(array $points, int $clusters) : void
{
$this->points = $points;
$n = \count($points);
$clusterCenters = $this->kpp($points, $clusters);
$coordinates = \count($points[0]->coordinates);
while (true) {
foreach ($clusterCenters as $center) {
for ($i = 0; $i < $coordinates; ++$i) {
$center->setCoordinate($i, 0);
}
}
foreach ($points as $point) {
$clusterPoint = $clusterCenters[$point->group];
++$clusterPoint->group;
for ($i = 0; $i < $coordinates; ++$i) {
$clusterPoint->setCoordinate($i, $clusterPoint->getCoordinate($i) + $point->getCoordinate($i));
}
}
foreach ($clusterCenters as $center) {
for ($i = 0; $i < $coordinates; ++$i) {
$center->setCoordinate($i, $center->getCoordinate($i) / $center->group);
}
}
$changed = 0;
foreach ($points as $point) {
$min = $this->nearestClusterCenter($point, $clusterCenters)[0];
if ($clusters !== $point->group) {
++$changed;
$point->group = $min;
}
}
if ($changed <= $n * self::EPSILON || $n * self::EPSILON < 2) {
break;
}
}
foreach ($clusterCenters as $key => $center) {
$center->group = $key;
$center->name = (string) $key;
}
$this->clusterCenters = $clusterCenters;
}
/**
* Get the index and distance to the nearest cluster center
*
* @param Point $point Point to get the cluster for
* @param Point[] $clusterCenters All cluster centers
*
* @return array [index, distance]
*
* @since 1.0.0
*/
private function nearestClusterCenter(Point $point, array $clusterCenters) : array
{
$index = $point->group;
$dist = \PHP_FLOAT_MAX;
foreach ($clusterCenters as $key => $cPoint) {
$d = ($this->metric)($cPoint, $point);
if ($dist > $d) {
$dist = $d;
$index = $key;
}
}
return [$index, $dist];
}
/**
* Initialize cluster centers
*
* @param Point[] $points Points to use for the cluster center initialization
* @param int<0, max> $n Amount of clusters to use
*
* @return Point[]
*
* @since 1.0.0
*/
private function kpp(array $points, int $n) : array
{
$clusters = [clone $points[\array_rand($points, 1)]];
$d = \array_fill(0, $n, 0.0);
for ($i = 1; $i < $n; ++$i) {
$sum = 0;
foreach ($points as $key => $point) {
$d[$key] = $this->nearestClusterCenter($point, $clusters)[1];
$sum += $d[$key];
}
$sum *= \mt_rand(0, \mt_getrandmax()) / \mt_getrandmax();
$found = false;
foreach ($d as $key => $di) {
$sum -= $di;
// The in array check is important to avoid duplicate cluster centers
if ($sum <= 0 && !\in_array($c = $points[$key], $clusters)) {
$clusters[$i] = clone $c;
$found = true;
}
}
while (!$found) {
if (!\in_array($c = $points[\array_rand($points)], $clusters)) {
$clusters[$i] = clone $c;
$found = true;
}
}
}
foreach ($points as $point) {
$point->group = $this->nearestClusterCenter($point, $clusters)[0];
}
return $clusters;
}
/**
* {@inheritdoc}
*/
public function getClusters() : array
{
if (!empty($this->clusters)) {
return $this->clusters;
}
foreach ($this->points as $point) {
$c = $this->cluster($point);
$this->clusters[$c?->name] = $point;
}
return $this->clusters;
}
}

View File

@ -0,0 +1,330 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
use phpOMS\Math\Topology\KernelsND;
use phpOMS\Math\Topology\MetricsND;
/**
* Clustering points
*
* @package phpOMS\Algorithm\Clustering
* @license OMS License 2.0
* @link https://jingga.app
* @see ./clustering_overview.png
* @since 1.0.0
*
* @todo Implement noise points
*/
final class MeanShift implements ClusteringInterface
{
/**
* Min distance for clustering
*
* As long as a point is further away as the min distance the shifting is performed
*
* @var float
* @since 1.0.0
*/
public const MIN_DISTANCE = 0.001;
/**
* Kernel function
*
* @var \Closure
* @since 1.0.0
*/
private \Closure $kernel;
/**
* Metric function
*
* @var \Closure
* @since 1.0.0
*/
private \Closure $metric;
private array $points;
/**
* Points outside of any cluster
*
* @var Point[]
* @since 1.0.0
*/
private array $noisePoints = [];
/**
* Cluster points
*
* Points in clusters (helper to avoid looping the cluster array)
*
* @var array
* @since 1.0.0
*/
private array $clusters = [];
/**
* Points of the cluster centers
*
* @var Point[]
* @since 1.0.0
*/
private array $clusterCenters = [];
/**
* Max distance to cluster to be still considered part of cluster
*
* @var float
* @since 1.0.0
*/
public float $groupDistanceTolerance = 0.1;
/**
* Constructor
*
* Both the metric and kernel function need to be of the same dimension.
*
* @param null|\Closure $metric Metric to use for the distance between two points
* @param null|\Closure $kernel Kernel
*
* @since 1.0.0
*/
public function __construct(?\Closure $metric = null, ?\Closure $kernel = null)
{
$this->metric = $metric ?? function (Point $a, Point $b) {
$aCoordinates = $a->coordinates;
$bCoordinates = $b->coordinates;
return MetricsND::euclidean($aCoordinates, $bCoordinates);
};
$this->kernel = $kernel ?? function (array $distances, array $bandwidths) {
return KernelsND::gaussianKernel($distances, $bandwidths);
};
}
/**
* Generate the clusters of the points
*
* @param Point[] $points Points to cluster
* @param array<int|float> $bandwidth Bandwidth(s)
*
* @return void
*
* @since 1.0.0
*/
public function generateClusters(array $points, array $bandwidth) : void
{
$this->points = $points;
$shiftPoints = $points;
$maxMinDist = 1;
$stillShifting = \array_fill(0, \count($points), true);
$pointLength = \count($shiftPoints);
while ($maxMinDist > self::MIN_DISTANCE) {
$maxMinDist = 0;
for ($i = 0; $i < $pointLength; ++$i) {
if (!$stillShifting[$i]) {
continue;
}
$pNew = $shiftPoints[$i];
$pNewStart = $pNew;
$pNew = $this->shiftPoint($pNew, $points, $bandwidth);
$dist = ($this->metric)($pNew, $pNewStart);
if ($dist > $maxMinDist) {
$maxMinDist = $dist;
}
if ($dist < self::MIN_DISTANCE) {
$stillShifting[$i] = false;
}
$shiftPoints[$i] = $pNew;
}
}
// @todo create an array of noisePoints like in the DBSCAN. That array can be empty or not depending on the bandwidth defined
$this->clusters = $this->groupPoints($shiftPoints);
$this->clusterCenters = $shiftPoints;
}
/**
* Perform shift on a point
*
* @param Point $point Point to shift
* @param Point $points Array of all points
* @param array<int|float> $bandwidth Bandwidth(s)
*
* @return Point
*
* @since 1.0.0
*/
private function shiftPoint(Point $point, array $points, array $bandwidth) : Point
{
$scaleFactor = 0.0;
$shifted = clone $point;
foreach ($points as $pTemp) {
$dist = ($this->metric)($point, $pTemp);
$weight = ($this->kernel)($dist, $bandwidth);
foreach ($point->coordinates as $idx => $_) {
if (!isset($shifted->coordinates[$idx])) {
$shifted->coordinates[$idx] = 0;
}
$shifted->coordinates[$idx] += $pTemp->coordinates[$idx] * $weight;
}
$scaleFactor += $weight;
}
foreach ($shifted->coordinates as $idx => $_) {
$shifted->coordinates[$idx] /= $scaleFactor;
}
return $shifted;
}
/**
* Group points together into clusters
*
* @param Point[] $points Array of points to assign to groups
*
* @return array
*
* @since 1.0.0
*/
private function groupPoints(array $points) : array
{
$groupAssignment = [];
$groups = [];
$groupIndex = 0;
foreach ($points as $point) {
$nearestGroupIndex = $this->findNearestGroup($point, $groups);
if ($nearestGroupIndex === -1) {
// create new group
$groups[] = [$point];
$groupAssignment[] = $groupIndex;
++$groupIndex;
} else {
$groupAssignment[] = $nearestGroupIndex;
$groups[$nearestGroupIndex][] = $point;
}
}
return $groupAssignment;
}
/**
* Find the closest cluster/group of a point
*
* @param Point $point Point to find the cluster for
* @param array<Point[]> $groups Clusters
*
* @return int
*
* @since 1.0.0
*/
private function findNearestGroup(Point $point, array $groups) : int
{
$nearestGroupIndex = -1;
$index = 0;
foreach ($groups as $group) {
$distanceToGroup = $this->distanceToGroup($point, $group);
if ($distanceToGroup < $this->groupDistanceTolerance) {
$nearestGroupIndex = $index;
break;
}
++$index;
}
return $nearestGroupIndex;
}
/**
* Find distance of point to best cluster/group
*
* @param Point $point Point to find the cluster for
* @param Point[] $group Clusters
*
* @return float Distance
*
* @since 1.0.0
*/
private function distanceToGroup(Point $point, array $group) : float
{
$minDistance = \PHP_FLOAT_MAX;
foreach ($group as $pt) {
$dist = ($this->metric)($point, $pt);
if ($dist < $minDistance) {
$minDistance = $dist;
}
}
return $minDistance;
}
/**
* {@inheritdoc}
*/
public function getCentroids() : array
{
return $this->clusterCenters;
}
/**
* {@inheritdoc}
*/
public function cluster(Point $point) : ?Point
{
$clusterId = $this->findNearestGroup($point, $this->clusters);
return $this->clusterCenters[$clusterId] ?? null;
}
/**
* {@inheritdoc}
*/
public function getNoise() : array
{
return $this->noisePoints;
}
/**
* {@inheritdoc}
*/
public function getClusters() : array
{
return $this->clusters;
}
}

96
Algorithm/Clustering/Point.php Executable file
View File

@ -0,0 +1,96 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
/**
* Point for clustering
*
* @package phpOMS\Algorithm\Clustering
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Point implements PointInterface
{
/**
* Coordinates of the point
*
* @var array<int, int|float>
* @since 1.0.0
*/
public array $coordinates = [];
/**
* Group or cluster this point belongs to
*
* @var int
* @since 1.0.0
*/
public int $group = 0;
/**
* Name of the point
*
* @var string
* @since 1.0.0
*/
public string $name = '';
/**
* Constructor.
*
* @param array<int, int|float> $coordinates Coordinates of the point
* @param string $name Name of the point
*
* @since 1.0.0
*/
public function __construct(array $coordinates, string $name = '')
{
$this->coordinates = $coordinates;
$this->name = $name;
}
/**
* {@inheritdoc}
*/
public function getCoordinates() : array
{
return $this->coordinates;
}
/**
* {@inheritdoc}
*/
public function getCoordinate(int $index) : int | float
{
return $this->coordinates[$index];
}
/**
* {@inheritdoc}
*/
public function setCoordinate(int $index, int | float $value) : void
{
$this->coordinates[$index] = $value;
}
/**
* {@inheritdoc}
*/
public function isEquals(Point $point) : bool
{
return $this->name === $point->name && $this->coordinates === $point->coordinates;
}
}

View File

@ -0,0 +1,77 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
/**
* Point interface.
*
* @property int $group Group
* @property string $name Name
* @property array $coordinates Coordinates
*
* @package phpOMS\Algorithm\Clustering;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*
* @property array<int, int|float> $coordinates
* @property string $name
* @property int $group
*/
interface PointInterface
{
/**
* Get the point coordinates
*
* @return array<int, int|float>
*
* @since 1.0.0
*/
public function getCoordinates() : array;
/**
* Get the coordinate of the point
*
* @param int $index Index of the coordinate (e.g. 0 = x);
*
* @return int|float
*
* @since 1.0.0
*/
public function getCoordinate(int $index) : int | float;
/**
* Set the coordinate of the point
*
* @param int $index Index of the coordinate (e.g. 0 = x);
* @param int|float $value Value of the coordinate
*
* @return void
*
* @since 1.0.0
*/
public function setCoordinate(int $index, int | float $value) : void;
/**
* Check if two points are equal
*
* @param Point $point Point to compare with
*
* @return bool
*
* @since 1.0.0
*/
public function isEquals(Point $point) : bool;
}

View File

@ -0,0 +1,61 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Clustering
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Clustering;
/**
* Clustering points
*
* @package phpOMS\Algorithm\Clustering
* @license OMS License 2.0
* @link https://jingga.app
* @see ./clustering_overview.png
* @since 1.0.0
*
* @todo Implement
*/
final class SpectralClustering implements ClusteringInterface
{
/**
* {@inheritdoc}
*/
public function getCentroids() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function getClusters() : array
{
return [];
}
/**
* {@inheritdoc}
*/
public function cluster(Point $point) : ?Point
{
return null;
}
/**
* {@inheritdoc}
*/
public function getNoise() : array
{
return [];
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 KiB

View File

@ -0,0 +1,76 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\CoinMatching
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\CoinMatching;
/**
* Matching a value with a set of coins
*
* @package phpOMS\Algorithm\CoinMatching
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class MinimumCoinProblem
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* Find the minimum amount of coins that are required to match a value
*
* @param array $coins Types of coins available (every coin has infinite availablity)
* @param int $value Value to match with the coins
*
* @return array
*
* @since 1.0.0
*/
public static function getMinimumCoinsForValueI(array $coins, int $value) : array
{
// amount of required coins for different values
$table = [0];
$usedCoins = [];
for ($i = 1; $i <= $value; ++$i) {
$table[$i] = \PHP_INT_MAX;
}
$m = \count($coins);
for ($i = 1; $i <= $value; ++$i) {
for ($j = 0; $j < $m; ++$j) {
if ($coins[$j] <= $i) {
$subRes = $table[$i - $coins[$j]];
if ($subRes !== \PHP_INT_MAX
&& $subRes + 1 < $table[$i]
) {
$table[$i] = $subRes + 1;
$usedCoins[$i] = $coins[$j] === null ? ($usedCoins[$i] ?? []) : \array_merge($usedCoins[$i - $coins[$j]] ?? [], [$coins[$j]]);
}
}
}
}
return $usedCoins[$value] ?? [];
}
}

View File

@ -0,0 +1,128 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Frequency
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Frequency;
/**
* Apriori algorithm.
*
* The algorithm checks how often a set exists in a given set of sets.
*
* @package phpOMS\Algorithm\Frequency
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class Apriori
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* Generate all possible subsets
*
* @param array $arr Array of elements
*
* @return array<array>
*
* @since 1.0.0
*/
private static function generateSubsets(array $arr) : array
{
$subsets = [[]];
foreach ($arr as $element) {
$newSubsets = [];
foreach ($subsets as $subset) {
$newSubsets[] = $subset;
$newSubsets[] = \array_merge($subset, [$element]);
}
$subsets = $newSubsets;
}
unset($subsets[0]);
return $subsets;
}
/**
* Performs the apriori algorithm.
*
* The algorithm cheks how often a set exists in a given set of sets.
*
* @param array<string[]> $sets Sets of a set (e.g. [[1,2,3,4], [1,2], [1]])
* @param string[] $subset Subset to check for (empty array -> all subsets are checked)
*
* @return array
*
* @since 1.0.0
*/
public static function apriori(array $sets, array $subset = []) : array
{
// Unique single items
$totalSet = [];
foreach ($sets as &$s) {
\sort($s);
foreach ($s as $item) {
$totalSet[] = $item;
}
}
$totalSet = \array_unique($totalSet);
\sort($totalSet);
\sort($subset);
// Combinations of items
$combinations = self::generateSubsets($totalSet);
// Table
$table = [];
foreach ($combinations as &$c) {
\sort($c);
if (!empty($subset) && $c !== $subset) {
continue;
}
$table[\implode(':', $c)] = 0;
}
foreach ($combinations as $combination) {
if (!empty($subset) && $combination !== $subset) {
continue;
}
foreach ($sets as $set) {
foreach ($combination as $item) {
if (!\in_array($item, $set)) {
continue 2;
}
}
++$table[\implode(':', $combination)];
}
}
return $table;
}
}

View File

@ -0,0 +1,84 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Graph;
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Graph;
/**
* Dependency resolver class.
*
* @package phpOMS\Algorithm\Graph;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class DependencyResolver
{
/**
* Resolve dependencies
*
* @param array $graph Graph to resolve
*
* @return null|array
*
* @since 1.0.0
*/
public static function resolve(array $graph) : ?array
{
$resolved = [];
$unresolved = [];
foreach ($graph as $table => $_) {
self::dependencyResolve($table, $graph, $resolved, $unresolved);
}
return empty($unresolved) ? $resolved : null;
}
/**
* Algorithm to resolve dependencies
*
* @param int|string $item Item id
* @param array<int|string, array> $items All items
*
* @return void
*
* @since 1.0.0
*/
private static function dependencyResolve(int | string $item, array $items, array &$resolved, array &$unresolved) : void
{
$unresolved[] = $item;
if (!isset($items[$item])) {
return;
}
foreach ($items[$item] as $dependency) {
if (!\in_array($dependency, $unresolved)) {
$unresolved[] = $dependency;
self::dependencyResolve($dependency, $items, $resolved, $unresolved);
} else {
return; // circular dependency
}
}
if (!\in_array($item, $resolved)) {
$resolved[] = $item;
}
foreach ($unresolved as $key => $unres) {
if ($unres === $item) {
unset($unresolved[$key]);
}
}
}
}

View File

@ -0,0 +1,205 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Graph
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Graph;
/**
* Markov chain
*
* @package phpOMS\Algorithm\Graph
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class MarkovChain
{
/**
* Order of the markov chain
*
* @var int
* @since 1.0.0
*/
private int $order = 1;
/**
* Trained data
*
* @var array
* @since 1.0.0
*/
private array $data = [];
/**
* Constructor
*
* @param int $order Order of the markov chain
*
* @since 1.0.0
*/
public function __construct(int $order = 1)
{
$this->order = $order;
}
/**
* Create markov chain based on input
*
* @param array $values Training values
*
* @return void
*
* @since 1.0.0
*/
public function train(array $values) : void
{
$temp = [];
$length = \count($values) - $this->order;
$unique = \array_unique($values);
for ($i = 0; $i < $length; ++$i) {
$key = [];
for ($j = 0; $j < $this->order; ++$j) {
$key[] = $values[$i + $j];
}
$keyString = \implode(' ', $key);
if (!isset($temp[$keyString])) {
foreach ($unique as $value) {
$temp[$keyString][$value] = 0;
}
}
++$temp[$keyString][$values[$i + 1]];
}
foreach ($temp as $key => $values) {
$sum = \array_sum($values);
foreach ($values as $idx => $value) {
$this->data[$key][$idx] = $value / $sum;
}
}
}
/**
* Set training data
*
* @param array<array<int, int>> $values Training values
*
* @return void
*
* @since 1.0.0
*/
public function setTraining(array $values) : void
{
$this->data = $values;
}
/**
* Generate a markov chain based on the training data.
*
* @param int $length Length of the markov chain
* @param array $start Start values of the markov chain
*
* @return array
*
* @since 1.0.0
*/
public function generate(int $length, ?array $start = null) : array
{
$orderKeys = \array_keys($this->data);
$orderValues = \array_keys(\reset($this->data));
$output = $start ?? \explode(' ', $orderKeys[\array_rand($orderKeys)]);
$key = $output;
for ($i = $this->order; $i < $length; ++$i) {
$keyString = \implode(' ', $key);
$prob = \mt_rand(1, 100) / 100;
$cProb = 0.0;
$val = null;
$new = null;
foreach (($this->data[$keyString] ?? []) as $val => $p) {
$cProb += $p;
if ($prob <= $cProb) {
$new = $val;
break;
}
}
// Couldn't find possible key
$new ??= $orderValues[\array_rand($orderValues)];
$output[] = $new;
$key[] = $new;
\array_shift($key);
}
return $output;
}
/**
* Calculate the probability for a certain markov chain.
*
* @param array $path Markov chain
*
* @return float
*
* @since 1.0.0
*/
public function pathProbability(array $path) : float
{
$length = \count($path);
if ($length <= $this->order) {
return 0.0;
}
$key = \array_slice($path, 0, $this->order);
$prob = 1.0;
for ($i = $this->order; $i < $length; ++$i) {
$prob *= $this->data[\implode(' ', $key)][$path[$i]] ?? 0.0;
$key[] = $path[$i];
\array_shift($key);
}
return $prob;
}
/**
* Calculate the probability for a certain state change in a markov chain
*
* @param array $state Current state of the markov chain
* @param mixed $next Next markov state
*
* @return float
*
* @since 1.0.0
*/
public function stepProbability(array $state, mixed $next) : float
{
if (\count($state) !== $this->order) {
return 0.0;
}
return $this->data[\implode(' ', $state)][$next] ?? 0.0;
}
}

99
Algorithm/JobScheduling/Job.php Executable file
View File

@ -0,0 +1,99 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\JobScheduling
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\JobScheduling;
/**
* Job for scheduling
*
* @package phpOMS\Algorithm\JobScheduling
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Job implements JobInterface
{
/**
* Value of the job
*
* @var float
* @since 1.0.0
*/
private float $value = 0.0;
/**
* Start time of the job
*
* @var \DateTime
* @since 1.0.0
*/
private \DateTime $start;
/**
* End time of the job
*
* @var \DateTime
* @since 1.0.0
*/
private ?\DateTime $end = null;
/**
* Name of the job
*
* @var string
* @since 1.0.0
*/
public string $name = '';
/**
* Constructor.
*
* @param float $value Value of the job
* @param \DateTime $start Start time of the job
* @param null|\DateTime $end End time of the job
*
* @since 1.0.0
*/
public function __construct(float $value, \DateTime $start, ?\DateTime $end, string $name = '')
{
$this->value = $value;
$this->start = $start;
$this->end = $end;
$this->name = $name;
}
/**
* {@inheritdoc}
*/
public function getValue() : float
{
return $this->value;
}
/**
* {@inheritdoc}
*/
public function getStart() : \DateTime
{
return $this->start;
}
/**
* {@inheritdoc}
*/
public function getEnd() : ?\DateTime
{
return $this->end;
}
}

View File

@ -0,0 +1,53 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\JobScheduling
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\JobScheduling;
/**
* Job interface.
*
* @package phpOMS\Algorithm\JobScheduling;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
interface JobInterface
{
/**
* Get value of the job
*
* @return float
*
* @since 1.0.0
*/
public function getValue() : float;
/**
* Get start time of the job
*
* @return \DateTime
*
* @since 1.0.0
*/
public function getStart() : \DateTime;
/**
* Get end time of the job
*
* @return \DateTime
*
* @since 1.0.0
*/
public function getEnd() : ?\DateTime;
}

View File

@ -0,0 +1,147 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\JobScheduling
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\JobScheduling;
/**
* Job scheduling algorithm with no overlapping jobs
*
* @package phpOMS\Algorithm\JobScheduling
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class Weighted
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* Sort jobs by end date.
*
* @param JobInterface $j1 Job 1
* @param JobInterface $j2 Job 2
*
* @return int
*
* @since 1.0.0
*/
private static function sortByEnd(JobInterface $j1, JobInterface $j2) : int
{
if ($j1->getEnd() === null && $j2->getEnd() !== null) {
return 1;
}
if ($j1->getEnd() === null && $j2->getEnd() === null) {
return 0;
}
if ($j1->getEnd() !== null && $j2->getEnd() === null) {
return -1;
}
return $j1->getEnd()->getTimestamp() <=> $j2->getEnd()->getTimestamp();
}
/**
* Search for a none-conflicting job that comes before a defined job
*
* @param JobInterface[] $jobs List of jobs
* @param int $pivot Job to find the previous job to
*
* @return int
*
* @since 1.0.0
*/
private static function binarySearch(array $jobs, int $pivot) : int
{
$lo = 0;
$hi = $pivot - 1;
while ($lo <= $hi) {
$mid = (int) (($lo + $hi) / 2);
if ($jobs[$mid]->getEnd() !== null
&& $jobs[$mid]->getEnd()->getTimestamp() <= $jobs[$pivot]->getStart()->getTimestamp()
) {
if ($jobs[$mid + 1]->getEnd() !== null
&& $jobs[$mid + 1]->getEnd()->getTimestamp() <= $jobs[$pivot]->getStart()->getTimestamp()
) {
$lo = $mid + 1;
} else {
return $mid;
}
} else {
$hi = $mid - 1;
}
}
return -1;
}
/**
* Maximize the value of the job execution without overlapping jobs
*
* @param JobInterface[] $jobs Jobs to filter
*
* @return JobInterface[]
*
* @since 1.0.0
*/
public static function solve(array $jobs) : array
{
$n = \count($jobs);
if ($n < 2) {
return $jobs;
}
\usort($jobs, function (\phpOMS\Algorithm\JobScheduling\JobInterface $j1, \phpOMS\Algorithm\JobScheduling\JobInterface $j2) : int {
return self::sortByEnd($j1, $j2);
});
$valueTable = [$jobs[0]->getValue()];
$resultTable = [];
$resultTable[0] = [$jobs[0]];
for ($i = 1; $i < $n; ++$i) {
$value = $jobs[$i]->getValue();
$jList = [$jobs[$i]];
$l = self::binarySearch($jobs, $i);
if ($l != -1) {
$value += $valueTable[$l];
$jList = \array_merge($resultTable[$l], $jList);
}
if ($value > $valueTable[$i - 1]) {
$valueTable[$i] = $value;
$resultTable[$i] = $jList;
} else {
$valueTable[$i] = $valueTable[$i - 1];
$resultTable[$i] = $resultTable[$i - 1];
}
}
return $resultTable[$n - 1];
}
}

View File

@ -0,0 +1,34 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Scheduling\Dependency;
/**
* Machine type.
*
* @package phpOMS\Scheduling\Dependency
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class IdleIntervalType
{
public const ACTIVE_TIME = 1; // every x hours of activity
public const JOB_TIME = 2; // every x jobs
public const FIXED_TIME = 3; // datetime
public const GENERAL_TIME = 4; // every x hours
}

View File

@ -0,0 +1,36 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Scheduling\Dependency;
/**
* Idle time.
*
* @package phpOMS\Scheduling\Dependency
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class IdleTime
{
public int $id = 0;
public int $type = 0; // setup, shutdown, cleaning, maintenance, general, ...
public int $intervalType = IdleIntervalType::ACTIVE_TIME;
public int $interval = 0;
public int $duration = 0; // in seconds
}

View File

@ -0,0 +1,73 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Scheduling\Dependency;
/**
* Job step.
*
* @package phpOMS\Scheduling\Dependency
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class JobStep
{
public int $id = 0;
public int $order = 0;
public int $l11n = 0;
public int $machineType = 0;
public bool $machineParallelization = false;
public array $machines = [];
public int $workerType = 0;
public array $workerQualifications = []; // qualifications needed
public bool $workerParallelization = false;
public array $workers = [];
public int $material = 0;
public int $materialQuantity = 0;
public int $duration = 0; // in seconds
public int $maxHoldTime = -1; // minutes it can be halted if necessary (-1 infinite, 0 not at all)
public int $maxHoldAfterCompletion = -1; // minutes the next processing step can be postponed (-1 infinite, 0 not at all)
private int $realDuration = 0;
// depending on job completions
private array $jobDependencies = [];
public bool $shouldBeParallel = false;
/**
* Duration
* + machine type/machine specific times (e.g. setup time etc.)
* + machine-job specific times (e.g. setup time for this job which could be different from the general machine setup time)
*/
public function calculateDuration() : void
{
$this->realDuration = $this->duration;
}
}

View File

@ -0,0 +1,32 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Scheduling\Dependency;
/**
* Machine.
*
* @package phpOMS\Scheduling\Dependency
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Machine
{
public int $id = 0;
public MachineType $type;
public array $idle = [];
}

View File

@ -0,0 +1,35 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Scheduling\Dependency;
/**
* Machine type.
*
* @package phpOMS\Scheduling\Dependency
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class MachineType
{
public int $id = 0;
public array $idle = [];
public array $qualifications = []; // qualifications needed
// array of arrays, where each operator type requires certain qualifications
public array $workerTypes = [];
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Scheduling\Dependency;
/**
* Material.
*
* @package phpOMS\Scheduling\Dependency
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Material
{
public int $id = 0;
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Scheduling\Dependency;
/**
* Material.
*
* @package phpOMS\Scheduling\Dependency
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Qualification
{
public int $id = 0;
}

View File

@ -0,0 +1,34 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Scheduling\Dependency;
/**
* Worker.
*
* @package phpOMS\Scheduling\Dependency
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Worker
{
public int $id = 0;
public int $type = 0;
public array $idle = [];
public array $qualifications = [];
}

View File

@ -0,0 +1,32 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Scheduling\Dependency
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Scheduling\Dependency;
/**
* Worker.
*
* @package phpOMS\Scheduling\Dependency
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class WorkerType
{
public int $id = 0;
public array $idle = [];
public array $qualifications = [];
}

View File

@ -0,0 +1,120 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Scheduling
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Scheduling;
/**
* Job.
*
* @package phpOMS\Scheduling
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Job
{
/**
* Id
*
* @var int
* @since 1.0.0
*/
public int $id = 0;
/**
* Time of the execution
*
* @var int
* @since 1.0.0
*/
public int $executionTime = 0;
/**
* Priority.
*
* @var float
* @since 1.0.0
*/
public float $priority = 0.0;
/**
* Value this job generates.
*
* @var float
* @since 1.0.0
*/
public float $value = 0.0;
/**
* Cost of executing this job.
*
* @var float
* @since 1.0.0
*/
public float $cost = 0.0;
/**
* How many iterations has this job been on hold in the queue.
*
* @var int
* @since 1.0.0
*/
public int $onhold = 0;
/**
* How many iterations has this job been in process in the queue.
*
* @var int
* @since 1.0.0
*/
public int $inprocessing = 0;
/**
* What is the deadline for this job?
*
* @param \DateTime
* @since 1.0.0
*/
public \DateTime $deadline;
/**
* Which steps must be taken during the job execution
*
* @var JobStep[]
* @since 1.0.0
*/
public array $steps = [];
/**
* Constructor.
*
* @since 1.0.0
*/
public function __construct()
{
$this->deadline = new \DateTime('now');
}
/**
* Get the profit of the job
*
* @return float
*
* @since 1.0.0
*/
public function getProfit() : float
{
return $this->value - $this->cost;
}
}

View File

@ -0,0 +1,128 @@
# Notes
## Job / Item
1. output item
2. output quantity
3. output scale factor
4. instruction manuals []
5. steps []
### Data
For single item, for this specific job (quantity plays a role) and for the current state
1. Work time planned/actual
1.1. Per worker type
1.2. Total
2. Machine time planned/actual
2.1. Per machine type
2.2. Total
3. Total duration planned/actual (is NOT work time + machine time)
4. Machines types required incl. quantity
5. Worker types required incl. quantity
6. Material costs
7. Worker costs
7.1. Per worker type
7.2. Total
8. Machine costs
8.1. Per machine type
8.2. Total
9. Progress status in %
10. Progress type (time based, step based, manual)
11. Value planned/actual
11. Costs planned/actual
12. Current step
## Steps
1. Setup machine
1.1. worker types required []
1.1.1. qualifications required by worker type []
1.1.2. defined after algorithm: workers []
1.1.2.1. worker specific qualifications available []
1.2. amount of workers per type required
1.3. worker scale factor (0 = no scaling, 1 = 100% scaling)
1.4. machine types required []
1.4.1. qualifications required by machine type []
1.4.2. min capacity
1.4.3. max capacity
1.4.4. defined after algorithm: machines []
1.4.4.1. machine specific qualifications required by machine type []
1.4.4.2. machine specific min capacity
1.4.4.3. machine specific max capacity
1.5. amount of machines per type required
1.6. machine scale factor (0 = no scaling, 1 = 100% scaling)
1.7. worker / machine correlation (1 = equal scaling required, > 1 = more workers required per machine scale, < 1 = less workers required per machine scale (e.g. 1.5 -> 150% additional worker required if machines are scaled by 100%, 0.8 -> 80% additional worker required if machines are scaled by 100%))
1.8. worker duration
1.8.1. planned
1.8.1. current/actual
1.9. machine duration
1.9.1. planned
1.9.1. current/actual
1.10. total duration
1.10.1. planned
1.10.1. current/actual
1.11. duration scale factor (1 = duration equally scaled as machine/worker scaling, > 1 = longer duration with scaling, < 1 = shorter duration with scaling (e.g. 1.1 -> 110% additional duration if scaled by 100%, 0.9 -> 90 % additional duration if scaled by 100%)). The scale factor is max(worker scale, machine scale);
1.12. depends on steps []
1.13. try to parallelize? (planned/actual)
1.14. material required []
1.14.1. material id
1.14.2. planned quantity
1.14.2. actual quantity
1.15. instruction checklist []
1.16. hold time during
1.16. hold time until next stip
2. Insert material 1
3. Insert material 2
4. Mix material
5. Quality control
6. Average correction
7. Insert material 3
8. Insert material 4
9. Mix material
10. Quality control
11. Average correction
12. Fill into large bindings
13. Fill into smaller bindings
14. Quality control
15. Packaging
## Algorithm
1. Try to manufacture in one go (no large breaks in between)
2. Try to parallelize (minimize time needed for production)
3. Match deadline (if no deadline available go to "find earliest possible deadline")
3.1. Priorize close or early to deadline finish (settings dependant)
3.2. If not possilbe re-adjust pending production
3.2.1. Focus on (value, cost, ...) (settings dependant)
3.2.2. If not possible re-adjust ongoing production
3.2.2.1. Focus on (value, cost, ...) (settings dependant)
3.2.2.2. If not possible find earliest possible deadline
Constraints / To consider
1. Deadline (maybe not defined)
2. Machines
2.1. Available
2.2.1. Other jobs
2.2.2. General maintenance cleaning
2.2.3. Unforseable maintenance
2.2. Scalability by a factor
3. Worker
2.2. Available
2.2.1. Other jobs
2.2.2. General maintenance cleaning
2.2.3. Vacation/sick
2.2. Qualification
2.3. Scalability by a factor
4. Job variance (multiple corrections required)
5. Material
4.1. Available
4.2. Delivery time
6. Parallelizability
7. Stock space
8. Putting job steps on hold
9. max/min capacities
10. Scaling factors

View File

@ -0,0 +1,46 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Scheduling
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Scheduling;
use phpOMS\Stdlib\Base\Enum;
/**
* Priority type enum.
*
* Defines the different priorities in which elements from the queue can be extracted.
*
* @package phpOMS\Scheduling
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
abstract class PriorityMode extends Enum
{
public const FIFO = 1; // First in first out
public const LIFO = 2; // Last in first out
public const PRIORITY = 4;
public const VALUE = 8;
public const COST = 16;
public const PROFIT = 32;
public const HOLD = 64; // Longest on hold
public const EARLIEST_DEADLINE = 128; // EDF
}

View File

@ -0,0 +1,213 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Scheduling
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Scheduling;
/**
* Scheduler.
*
* @package phpOMS\Scheduling
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class ScheduleQueue
{
/**
* Queue
*
* @var Job[]
* @since 1.0.0
*/
public array $queue = [];
/**
* Get element from queue
*
* @param int $size Amount of elements to return
* @param int $type Priority type to use for return
*
* @return Job[]
*
* @since 1.0.0
*/
public function get(int $size = 1, int $type = PriorityMode::FIFO) : array
{
$jobs = [];
$keys = \array_keys($this->queue);
switch ($type) {
case PriorityMode::FIFO:
for ($i = 0; $i < $size; ++$i) {
$jobs[$i] = $this->queue[$keys[$i]];
}
break;
case PriorityMode::LIFO:
for ($i = \count($this->queue) - $size - 1; $i < $size; ++$i) {
$jobs[$i] = $this->queue[$keys[$i]];
}
break;
case PriorityMode::PRIORITY:
$queue = $this->queue;
\uasort($queue, function (Job $a, Job $b) {
return $a->priority <=> $b->priority;
});
$jobs = \array_slice($queue, 0, $size, true);
break;
case PriorityMode::VALUE:
$queue = $this->queue;
\uasort($queue, function (Job $a, Job $b) {
return $b->value <=> $a->value;
});
$jobs = \array_slice($queue, 0, $size, true);
break;
case PriorityMode::COST:
$queue = $this->queue;
\uasort($queue, function (Job $a, Job $b) {
return $a->cost <=> $b->cost;
});
$jobs = \array_slice($queue, 0, $size, true);
break;
case PriorityMode::PROFIT:
$queue = $this->queue;
\uasort($queue, function (Job $a, Job $b) {
return $b->getProfit() <=> $a->getProfit();
});
$jobs = \array_slice($queue, 0, $size, true);
break;
case PriorityMode::HOLD:
$queue = $this->queue;
\uasort($queue, function (Job $a, Job $b) {
return $b->onhold <=> $a->onhold;
});
$jobs = \array_slice($queue, 0, $size, true);
break;
case PriorityMode::EARLIEST_DEADLINE:
$queue = $this->queue;
\uasort($queue, function (Job $a, Job $b) {
return $a->deadline->getTimestamp() <=> $b->deadline->getTimestamp();
});
$jobs = \array_slice($queue, 0, $size, true);
break;
}
return $jobs;
}
/**
* Insert new element into queue
*
* @param int $id Element id
* @param Job $job Element to add
*
* @return void
*
* @since 1.0.0
*/
public function insert(int $id, Job $job) : void
{
$this->queue[$id] = $job;
}
/**
* Pop elements from the queue.
*
* This also removes the elements from the queue
*
* @param int $size Amount of elements to return
* @param int $type Priority type to use for return
*
* @return Job[]
*
* @since 1.0.0
*/
public function pop(int $size = 1, int $type = PriorityMode::FIFO) : array
{
$jobs = $this->get($size, $type);
foreach ($jobs as $id => $_) {
unset($this->queue[$id]);
}
return $jobs;
}
/**
* Increases the hold counter of an element
*
* @param int $id Id of the element (0 = all elements)
*
* @return void
*
* @since 1.0.0
*/
public function bumpHold(int $id = 0) : void
{
if ($id === 0) {
foreach ($this->queue as $job) {
++$job->onhold;
}
} else {
++$this->queue[$id]->onhold;
}
}
/**
* Change the priority of an element
*
* @param int $id Id of the element (0 = all elements)
* @param float $priority Priority to increase by
*
* @return void
*
* @since 1.0.0
*/
public function adjustPriority(int $id = 0, float $priority = 0.1) : void
{
if ($id === 0) {
foreach ($this->queue as $job) {
$job->priority += $priority;
}
} else {
$this->queue[$id]->priority += $priority;
}
}
/**
* Remove an element from the queue
*
* @param int $id Id of the element
*
* @return void
*
* @since 1.0.0
*/
public function remove(int $id) : void
{
unset($this->queue[$id]);
}
}

112
Algorithm/Knapsack/Backpack.php Executable file
View File

@ -0,0 +1,112 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Knapsack
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Knapsack;
/**
* Backpack for the Knapsack problem
*
* @package phpOMS\Algorithm\Knapsack
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Backpack implements BackpackInterface
{
/**
* Maximum amount of cost this backpack can hold
*
* @var float
* @since 1.0.0
*/
private float $maxCost = 0.0;
/**
* Current value
*
* @var float
* @since 1.0.0
*/
private float $value = 0.0;
/**
* Current cost
*
* @var float
* @since 1.0.0
*/
private float $cost = 0.0;
/**
* Items inside the backpack
*
* @var array<int, array{item:ItemInterface, quantity:int|float}>
* @since 1.0.0
*/
private array $items = [];
/**
* Constructor.
*
* @param float $maxCost Maximum amount of costs the backpack can hold
*
* @since 1.0.0
*/
public function __construct(float $maxCost)
{
$this->maxCost = $maxCost;
}
/**
* {@inheritdoc}
*/
public function getValue() : float
{
return $this->value;
}
/**
* {@inheritdoc}
*/
public function getCost() : float
{
return $this->cost;
}
/**
* {@inheritdoc}
*/
public function getMaxCost() : float
{
return $this->maxCost;
}
/**
* {@inheritdoc}
*/
public function getItems() : array
{
return $this->items;
}
/**
* {@inheritdoc}
*/
public function addItem(ItemInterface $item, int | float $quantity = 1) : void
{
$this->items[] = ['item' => $item, 'quantity' => $quantity];
$this->value += $item->getValue() * $quantity;
$this->cost += $item->getCost() * $quantity;
}
}

View File

@ -0,0 +1,74 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Knapsack
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Knapsack;
/**
* Backpack interface.
*
* @package phpOMS\Algorithm\Knapsack;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
interface BackpackInterface
{
/**
* Get the value of the stored items
*
* @return float
*
* @since 1.0.0
*/
public function getValue() : float;
/**
* Get the cost of the stored items
*
* @return float
*
* @since 1.0.0
*/
public function getCost() : float;
/**
* Get the max allowed costs for the items
*
* @return float
*
* @since 1.0.0
*/
public function getMaxCost() : float;
/**
* Get items
*
* @return array
*
* @since 1.0.0
*/
public function getItems() : array;
/**
* Add item to backpack
*
* @param ItemInterface $item Item
* @param int|float $quantity Quantity of the item
*
* @return void
*
* @since 1.0.0
*/
public function addItem(ItemInterface $item, int | float $quantity = 1) : void;
}

100
Algorithm/Knapsack/Bounded.php Executable file
View File

@ -0,0 +1,100 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Knapsack
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Knapsack;
/**
* Bounded knapsack algorithm
*
* This algorithm only works for integer cost, values and quantities!
*
* @package phpOMS\Algorithm\Knapsack
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class Bounded
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* Fill the backpack with items
*
* This algorithm only works for integer cost, values and quantities!
*
* @param array $items Items to fill the backpack with ['item' => Item, 'quantity' => ?]
* @param BackpackInterface $backpack Backpack to fill
*
* @return BackpackInterface
*
* @since 1.0.0
*/
public static function solve(array $items, BackpackInterface $backpack) : BackpackInterface
{
$n = \count($items);
// @var int<0, max> $maxCost
$maxCost = (int) $backpack->getMaxCost();
$mm = \array_fill(0, ($maxCost + 1), 0);
$m = [];
$m[0] = $mm;
for ($i = 1; $i <= $n; ++$i) {
$m[$i] = $mm;
for ($j = 0; $j <= $maxCost; ++$j) {
$m[$i][$j] = $m[$i - 1][$j];
for ($k = 1; $k <= $items[$i - 1]['quantity']; ++$k) {
if ($k * ((int) $items[$i - 1]['item']->getCost()) > $j) {
break;
}
$v = $m[$i - 1][$j - $k * ((int) $items[$i - 1]['item']->getCost())] + $k * ((int) $items[$i - 1]['item']->getValue());
if ($v > $m[$i][$j]) {
$m[$i][$j] = $v;
}
}
}
}
$s = 0;
for ($i = $n, $j = $maxCost; $i > 0; --$i) {
$s = 0;
$v = $m[$i][$j];
$value = (int) $items[$i - 1]['item']->getValue();
for ($k = 0; $v !== $m[$i - 1][$j] + $k * $value; ++$k) {
++$s;
$j -= (int) $items[$i - 1]['item']->getCost();
}
if ($s > 0) {
$backpack->addItem($items[$i - 1]['item'], $s);
}
}
return $backpack;
}
}

View File

@ -0,0 +1,84 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Knapsack
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Knapsack;
/**
* Continuous knapsack algorithm
*
* @package phpOMS\Algorithm\Knapsack
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class Continuous
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* Comparing items
*
* @param Item[] $a Item
* @param Item[] $b Item
*
* @return int
*
* @since 1.0.0
*/
private static function continuousComparator(array $a, array $b) : int
{
return $b['item']->getValue() / $b['item']->getCost() <=> $a['item']->getValue() / $a['item']->getCost();
}
/**
* Fill the backpack with items
*
* @param array $items Items to fill the backpack with ['item' => Item, 'quantity' => ?]
* @param BackpackInterface $backpack Backpack to fill
*
* @return BackpackInterface
*
* @since 1.0.0
*/
public static function solve(array $items, BackpackInterface $backpack) : BackpackInterface
{
/* @phpstan-ignore-next-line */
\usort($items, ['self', 'continuousComparator']);
$availableSpace = $backpack->getMaxCost();
foreach ($items as $item) {
if ($availableSpace <= 0.0) {
break;
}
$backpack->addItem(
$item['item'],
$quantity = \min($item['quantity'], $availableSpace / $item['item']->getCost())
);
$availableSpace -= $quantity * $item['item']->getCost();
}
return $backpack;
}
}

89
Algorithm/Knapsack/Item.php Executable file
View File

@ -0,0 +1,89 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Knapsack
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Knapsack;
/**
* Item in the Knapsack
*
* @package phpOMS\Algorithm\Knapsack
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Item implements ItemInterface
{
/**
* Value of the item
*
* @var float
* @since 1.0.0
*/
private float $value = 0.0;
/**
* Cost of the item
*
* @var float
* @since 1.0.0
*/
private float $cost = 0.0;
/**
* Name of the item
*
* @var string
* @since 1.0.0
*/
public string $name = '';
/**
* Constructor.
*
* @param float $value Value of the item
* @param float $cost Cost of the item
*
* @since 1.0.0
*/
public function __construct(float $value, float $cost, string $name = '')
{
$this->value = $value;
$this->cost = $cost;
$this->name = $name;
}
/**
* {@inheritdoc}
*/
public function getValue() : float
{
return $this->value;
}
/**
* {@inheritdoc}
*/
public function getCost() : float
{
return $this->cost;
}
/**
* {@inheritdoc}
*/
public function getName() : string
{
return $this->name;
}
}

View File

@ -0,0 +1,53 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Knapsack
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Knapsack;
/**
* Item interface.
*
* @package phpOMS\Algorithm\Knapsack;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
interface ItemInterface
{
/**
* Get value of the item
*
* @return float
*
* @since 1.0.0
*/
public function getValue() : float;
/**
* Get value of the item
*
* @return float
*
* @since 1.0.0
*/
public function getCost() : float;
/**
* Get the name of the item
*
* @return string
*
* @since 1.0.0
*/
public function getName() : string;
}

162
Algorithm/Maze/MazeGenerator.php Executable file
View File

@ -0,0 +1,162 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Maze
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Maze;
/**
* Maze generator
*
* @package phpOMS\Algorithm\Maze
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class MazeGenerator
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* Generate a random maze
*
* @param int<0, max> $width Width
* @param int<0, max> $height Height
*
* @return array
*
* @since 1.0.0
*/
public static function random(int $width, int $height) : array
{
$n = $height * $width - 1;
$horizontal = \array_fill(0, $height, []);
$vertical = \array_fill(0, $height, []);
$pos = [\mt_rand(0, $height) - 1, \mt_rand(0, $width) - 1];
$path = [$pos];
$unvisited = [];
for ($i = 0; $i < $height + 2; ++$i) {
$unvisited[] = [];
for ($j = 0; $j < $width + 1; ++$j) {
$unvisited[$i][] = $i > 0 && $i < $height + 1 && $j > 0 && ($i !== $pos[0] + 1 || $j != $pos[1] + 1);
}
}
while ($n > 0) {
$potential = [
[$pos[0] + 1, $pos[1]],
[$pos[0], $pos[1] + 1],
[$pos[0] - 1, $pos[1]],
[$pos[0], $pos[1] - 1],
];
$neighbors = [];
for ($i = 0; $i < 4; ++$i) {
if ($unvisited[$potential[$i][0] + 1][$potential[$i][1] + 1] ?? false) {
$neighbors[] = $potential[$i];
}
}
if (!empty($neighbors)) {
--$n;
$next = $neighbors[\array_rand($neighbors, 1)];
$unvisited[$next[0] + 1][$next[1] + 1] = false;
if ($next[0] === $pos[0]) {
$horizontal[$next[0]][($next[1] + $pos[1] - 1) / 2] = true;
} else {
$vertical[($next[0] + $pos[0] - 1) / 2][$next[1]] = true;
}
$path[] = $next;
$pos = $next;
} else {
$pos = \array_pop($path);
if ($pos === null) {
break; // @codeCoverageIgnore
}
}
}
$maze = [];
for ($i = 0; $i < $height * 2 + 1; ++$i) {
$line = [];
if ($i % 2 === 0) {
for ($j = 0; $j < $width * 4 + 1; ++$j) {
if ($j % 4 === 0) {
$line[$j] = '+'; // 9
} else {
$line[$j] = $i > 0 && ($vertical[$i / 2 - 1][(int) \floor($j / 4)] ?? false) ? ' ' : '-'; // 9
}
}
} else {
for ($j = 0; $j < $width * 4 + 1; ++$j) { // 2
if ($j % 4 === 0) {
$line[$j] = $j > 0 && ($horizontal[($i - 1) / 2][$j / 4 - 1] ?? false) ? ' ' : '|'; // 0 | 9
} else {
$line[$j] = ' '; // 0
}
}
}
if ($i === 0) {
$line[1] = $line[2] = $line[3] = ' '; // 0
}
if ($height * 2 - 1 === $i) {
$line[4 * $width] = ' '; // 2 - 0
}
$maze[] = $line;
}
return $maze;
}
/**
* Render a maze
*
* @param array<int, int[]> $maze Maze to render
*
* @return string
*
* @since 1.0.0
*/
public static function render(array $maze) : string
{
$rendered = '';
foreach ($maze as $row) {
foreach ($row as $column) {
$rendered .= $column;
}
$rendered .= "\n";
}
return $rendered;
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Optimization;
/**
* Perform ant colony algorithm.
*
* @package phpOMS\Algorithm\Optimization
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class AntColonyOptimization
{
}

View File

@ -0,0 +1,27 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Optimization;
/**
* Perform bees algorithm.
*
* @package phpOMS\Algorithm\Optimization
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class BeesAlgorithm
{
}

View File

@ -0,0 +1,27 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Optimization;
/**
* Perform firefly algorithm.
*
* @package phpOMS\Algorithm\Optimization
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class FireflyAlgorithm
{
}

View File

@ -0,0 +1,157 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Optimization;
/**
* Perform genetic algorithm (GA).
*
* @package phpOMS\Algorithm\Optimization
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class GeneticOptimization
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/*
// Fitness function (may require to pass solution space as \Closure variable)
// E.g.
// highest value of some sorts (e.g. profit)
// most elements (e.g. jobs)
// lowest costs
// combination of criteria = points (where some criteria are mandatory/optional)
public static function fitness($x)
{
return $x;
}
public static function mutate($parameters, $mutationRate)
{
for ($i = 0; $i < \count($parameters); $i++) {
if (\mt_rand(0, 1000) / 1000 < $mutationRate) {
$parameters[$i] = 1 - $parameters[$i];
}
}
return $parameters;
}
public static function crossover($parent1, $parent2, $parameterCount)
{
$crossoverPoint = \mt_rand(1, $parameterCount - 1);
$child1 = \array_merge(
\array_slice($parent1, 0, $crossoverPoint),
\array_slice($parent2, $crossoverPoint)
);
$child2 = \array_merge(
\array_slice($parent2, 0, $crossoverPoint),
\array_slice($parent1, $crossoverPoint)
);
return [$child1, $child2];
}
*/
/**
* Perform optimization
*
* @example See unit test for example use case
*
* @param array<array> $population List of all elements with their parameters (i.e. list of "objects" as arrays).
* The constraints are defined as array values.
* @param \Closure $fitness Fitness function calculates score/feasibility of solution
* @param \Closure $mutate Mutation function to change the parameters of an "object"
* @param \Closure $crossover Crossover function to exchange parameter values between "objects".
* Sometimes single parameters can be exchanged but sometimes interdependencies exist between parameters which is why this function is required.
* @param int $generations Number of generations to create
* @param float $mutationRate Rate at which parameters are changed.
* How this is used depends on the mutate function.
*
* @return array{solutions:array, fitnesses:float[]}
*
* @since 1.0.0
*/
public static function optimize(
array $population,
\Closure $fitness,
\Closure $mutate,
\Closure $crossover,
int $generations = 500,
float $mutationRate = 0.1
) : array
{
$populationSize = \count($population);
$parameterCount = $populationSize === 0 ? 0 : \count(\reset($population));
// Genetic Algorithm Loop
for ($generation = 0; $generation < $generations; ++$generation) {
$fitnessScores = [];
foreach ($population as $parameters) {
$fitnessScores[] = ($fitness)($parameters);
}
// Select parents for crossover based on fitness scores
$parents = [];
for ($i = 0; $i < $populationSize; ++$i) {
do {
$parentIndex1 = \array_rand($population);
$parentIndex2 = \array_rand($population);
} while ($parentIndex1 === $parentIndex2);
$parents[] = $fitnessScores[$parentIndex1] > $fitnessScores[$parentIndex2]
? $population[$parentIndex1]
: $population[$parentIndex2];
}
// Crossover and mutation to create next generation
$newPopulation = [];
for ($i = 0; $i < $populationSize; $i += 2) {
$crossover = ($crossover)($parents[$i], $parents[$i + 1], $parameterCount);
$child1 = ($mutate)($crossover[0], $mutationRate);
$child2 = ($mutate)($crossover[1], $mutationRate);
$newPopulation[] = $child1;
$newPopulation[] = $child2;
}
$population = $newPopulation;
}
$fitnesses = [];
foreach ($population as $key => $parameters) {
$fitnesses[$key] = ($fitness)($parameters);
}
\asort($fitnesses);
return [
'solutions' => $population,
'fitnesses' => $fitnesses,
];
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Optimization;
/**
* Perform harmony search algorithm.
*
* @package phpOMS\Algorithm\Optimization
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class HarmonySearch
{
}

View File

@ -0,0 +1,27 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Optimization;
/**
* Perform intelligent water drops algorithm.
*
* @package phpOMS\Algorithm\Optimization
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class IntelligentWaterDrops
{
}

View File

@ -0,0 +1,113 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Optimization;
/**
* Perform simulated annealing (SA).
*
* @package phpOMS\Algorithm\Optimization
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class SimulatedAnnealing
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/*
public static function costFunction($x)
{
return $x;
}
// can be many things, e.g. swapping parameters, increasing/decreasing, random generation
public static function neighbor(array $generation, $parameterCount)
{
$newGeneration = $generation;
$randomIndex1 = \mt_rand(0, $parameterCount - 1);
$randomIndex2 = \mt_rand(0, $parameterCount - 1);
// Swap two cities in the route
$temp = $newGeneration[$randomIndex1];
$newGeneration[$randomIndex1] = $newGeneration[$randomIndex2];
$newGeneration[$randomIndex2] = $temp;
return $newGeneration;
}
*/
// Simulated Annealing algorithm
// @todo allow to create a solution space (currently all solutions need to be in space)
// @todo currently only replacing generations, not altering them
/**
* Perform optimization
*
* @example See unit test for example use case
*
* @param array $space List of all elements with their parameters (i.e. list of "objects" as arrays).
* The constraints are defined as array values.
* @param int $initialTemperature Starting temperature
* @param \Closure $costFunction Fitness function calculates score/feasibility of solution
* @param \Closure $neighbor Neighbor function to find a new solution/neighbor
* @param float $coolingRate Rate at which cooling takes place
* @param int $iterations Number of iterations
*
* @return array{solutions:array, costs:float[]}
*
* @since 1.0.0
*/
public function optimize(
array $space,
int $initialTemperature,
\Closure $costFunction,
\Closure $neighbor,
float $coolingRate = 0.98,
int $iterations = 1000
) : array
{
$parameterCount = \count($space);
$currentGeneration = \reset($space);
$currentCost = ($costFunction)($currentGeneration);
for ($i = 0; $i < $iterations; ++$i) {
$newGeneration = ($neighbor)($currentGeneration, $parameterCount);
$newCost = ($costFunction)($newGeneration);
$temperature = $initialTemperature * \pow($coolingRate, $i);
if ($newCost < $currentCost
|| \mt_rand() / \mt_getrandmax() < \exp(($currentCost - $newCost) / $temperature)
) {
$currentGeneration = $newGeneration;
$currentCost = $newCost;
}
}
return [
'solutions' => $currentGeneration,
'costs' => $currentCost,
];
}
}

View File

@ -0,0 +1,118 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Optimization
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Optimization;
/**
* Perform tabu search.
*
* @package phpOMS\Algorithm\Optimization
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class TabuSearch
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/*
// Define your fitness function here
public static function fitness($solution) {
// Calculate and return the fitness of the solution
// This function should be tailored to your specific problem
return $solution;
}
// Define your neighborhood generation function here
public static function generateNeighbor($currentSolution) {
// Generate a neighboring solution based on the current solution
// This function should be tailored to your specific problem
return $currentSolution;
}
*/
/**
* Perform optimization
*
* @example See unit test for example use case
*
* @param array $initialSolution List of all elements with ther parameters (i.e. list of "objects" as arrays).
* The constraints are defined as array values.
* @param \Closure $fitness Fitness function calculates score/feasability of solution
* @param \Closure $neighbor Neighbor function to find a new solution/neighbor
* @param int $tabuListSize ????
* @param int $iterations Number of iterations
*
* @return array
*
* @since 1.0.0
*/
public static function optimize(
array $initialSolution,
\Closure $fitness,
\Closure $neighbor,
int $tabuListSize,
int $iterations
) : array
{
$currentSolution = $initialSolution;
$bestSolution = $currentSolution;
$bestFitness = \PHP_FLOAT_MIN;
$tabuList = [];
for ($i = 0; $i < $iterations; ++$i) {
$neighbors = [];
for ($j = 0; $j < $tabuListSize; ++$j) {
$neighbor = ($neighbor)($currentSolution);
$neighbors[] = $neighbor;
}
$bestNeighbor = null;
foreach ($neighbors as $neighbor) {
if (!\in_array($neighbor, $tabuList) &&
($bestNeighbor === null
|| ($fitness)($neighbor) > ($fitness)($bestNeighbor))
) {
$bestNeighbor = $neighbor;
}
}
if ($bestNeighbor === null) {
break;
}
$tabuList[] = $bestNeighbor;
if (\count($tabuList) > $tabuListSize) {
\array_shift($tabuList);
}
$currentSolution = $bestNeighbor;
if (($score = ($fitness)($bestNeighbor)) > $bestFitness) {
$bestSolution = $bestNeighbor;
$bestFitness = $score;
}
}
return $bestSolution;
}
}

116
Algorithm/PathFinding/AStar.php Executable file
View File

@ -0,0 +1,116 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*
* Extended based on:
* MIT License
* (c) 2011-2012 Xueqiao Xu <xueqiaoxu@gmail.com>
* (c) PathFinding.js
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\PathFinding;
use phpOMS\Stdlib\Base\Heap;
/**
* Perform path finding.
*
* @package phpOMS\Algorithm\PathFinding
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class AStar implements PathFinderInterface
{
/**
* {@inheritdoc}
*/
public static function findPath(
int $startX, int $startY,
int $endX, int $endY,
Grid $grid,
int $heuristic, int $movement
) : Path
{
/** @var null|AStarNode $startNode */
$startNode = $grid->getNode($startX, $startY);
/** @var null|AStarNode $endNode */
$endNode = $grid->getNode($endX, $endY);
if ($startNode === null || $endNode === null) {
return new Path($grid);
}
$startNode->setG(0.0);
$startNode->setF(0.0);
$startNode->setOpened(true);
$openList = new Heap(function (AStarNode $node1, AStarNode $node2) {
return $node1->getF() - $node2->getF();
});
$openList->push($startNode);
$node = null;
while (!$openList->isEmpty()) {
$node = $openList->pop();
if ($node === null) {
break;
}
/** @var AStarNode $node */
$node->setClosed(true);
if ($node->isEqual($endNode)) {
break;
}
/** @var AStarNode[] $neighbors */
$neighbors = $grid->getNeighbors($node, $movement);
$neighborsLength = \count($neighbors);
for ($i = 0; $i < $neighborsLength; ++$i) {
$neighbor = $neighbors[$i];
if ($neighbor->isClosed()) {
continue;
}
$ng = $node->getG() + (($neighbor->getX() - $node->getX() === 0 || $neighbor->getY() - $node->getY() === 0) ? 1 : \sqrt(2));
if (!$neighbor->isOpened() || $ng < $neighbor->getG()) {
$neighbor->setG($ng);
$neighbor->setH($neighbor->getH() ?? (
$neighbor->getWeight() * Heuristic::metric($neighbor->getCoordinates(), $endNode->getCoordinates(), $heuristic)
));
$neighbor->setF($neighbor->getG() + $neighbor->getH());
$neighbor->parent = $node;
if (!$neighbor->isOpened()) {
$openList->push($neighbor);
$neighbor->setOpened(true);
} else {
$openList->update($neighbor);
}
}
}
}
$path = new Path($grid);
while ($node !== null) {
$path->addNode($node);
$node = $node->parent;
}
return $path;
}
}

View File

@ -0,0 +1,196 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\PathFinding;
/**
* Node on grid.
*
* @package phpOMS\Algorithm\PathFinding
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class AStarNode extends Node
{
/**
* The g score is cost of the path
*
* @var float
* @since 1.0.0
*/
private float $g = 0.0;
/**
* The heuristic distance is the cost to the end node
*
* @var float
* @since 1.0.0
*/
private ?float $h = null;
/**
* The f score is defined as f(n) = g(n) + h(n)
*
* @var float
* @since 1.0.0
*/
private float $f = 0.0;
/**
* Define as checked node
*
* @var bool
* @since 1.0.0
*/
private bool $isClosed = false;
/**
* Define as potential candidate
*
* @var bool
* @since 1.0.0
*/
private bool $isOpened = false;
/**
* Is checked?
*
* @return bool
*
* @since 1.0.0
*/
public function isClosed() : bool
{
return $this->isClosed;
}
/**
* Is potential candidate
*
* @return bool
*
* @since 1.0.0
*/
public function isOpened() : bool
{
return $this->isOpened;
}
/**
* Set check status
*
* @param bool $isClosed Is closed
*
* @return void
*
* @since 1.0.0
*/
public function setClosed(bool $isClosed) : void
{
$this->isClosed = $isClosed;
}
/**
* Set potential candidate
*
* @param bool $isOpened Is potential candidate
*
* @return void
*
* @since 1.0.0
*/
public function setOpened(bool $isOpened) : void
{
$this->isOpened = $isOpened;
}
/**
* Set the g score
*
* @param float $g G score
*
* @return void
*
* @since 1.0.0
*/
public function setG(float $g) : void
{
$this->g = $g;
}
/**
* Set the heuristic distance
*
* @param float $h H distance
*
* @return void
*
* @since 1.0.0
*/
public function setH(?float $h) : void
{
$this->h = $h;
}
/**
* Set the f score
*
* @param float $f F score
*
* @return void
*
* @since 1.0.0
*/
public function setF(float $f) : void
{
$this->f = $f;
}
/**
* Get the g score
*
* @return float
*
* @since 1.0.0
*/
public function getG() : float
{
return $this->g;
}
/**
* Get the heuristic distance
*
* @return float
*
* @since 1.0.0
*/
public function getH() : ?float
{
return $this->h;
}
/**
* Get the f score
*
* @return float
*
* @since 1.0.0
*/
public function getF() : float
{
return $this->f;
}
}

225
Algorithm/PathFinding/Grid.php Executable file
View File

@ -0,0 +1,225 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*
* Extended based on:
* MIT License
* (c) 2011-2012 Xueqiao Xu <xueqiaoxu@gmail.com>
* (c) PathFinding.js
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\PathFinding;
/**
* Grid of nodes.
*
* @package phpOMS\Algorithm\PathFinding
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Grid
{
/**
* Grid system containing all nodes
*
* @var array<int, array<int, Node>>
* @since 1.0.0
*/
private array $nodes = [[]];
/**
* Create a grid from an array
*
* [
* [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,],
* [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,],
* [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,],
* [0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,],
* [0, 0, 0, 0, 9, 9, 9, 9, 9, 0, 9, 0, 0, 0, 0,],
* [0, 0, 1, 0, 9, 0, 0, 0, 0, 0, 9, 0, 9, 9, 9,],
* [0, 0, 0, 0, 9, 0, 0, 9, 9, 9, 9, 0, 0, 0, 0,],
* [0, 0, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,],
* [0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 9, 9, 9, 9, 0,],
* [0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,],
* [0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 9, 9, 0, 0, 0,],
* [0, 0, 0, 0, 0, 9, 9, 9, 0, 0, 9, 2, 0, 0, 0,],
* [0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 9, 9, 0, 0, 0,],
* [0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,],
* [0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,],
* ]
*
* @param array<int, int[]> $gridArray Grid defined in an array (0 = empty, 1 = start, 2 = end, 9 = not walkable)
* @param string $node Node type name
*
* @return Grid
*
* @since 1.0.0
*/
public static function createGridFromArray(array $gridArray, string $node) : self
{
$grid = new self();
foreach ($gridArray as $y => $yRow) {
foreach ($yRow as $x => $xElement) {
if ($xElement === 0 || $xElement === 1 || $xElement === 2) {
/** @var \phpOMS\Algorithm\PathFinding\Node $empty */
$empty = new $node($x, $y, 1.0, true);
$grid->setNode($x, $y, $empty);
} elseif ($xElement === 9) {
/** @var \phpOMS\Algorithm\PathFinding\Node $wall */
$wall = new $node($x, $y, 1.0, false);
$grid->setNode($x, $y, $wall);
}
}
}
return $grid;
}
/**
* Set node at position
*
* @param int $x X-Coordinate
* @param int $y Y-Coordinate
* @param Node $node Node to set
*
* @return void
*
* @since 1.0.0
*/
public function setNode(int $x, int $y, Node $node) : void
{
$this->nodes[$y][$x] = $node;
}
/**
* Get node at position
*
* @param int $x X-Coordinate
* @param int $y Y-Coordinate
*
* @return null|Node
*
* @since 1.0.0
*/
public function getNode(int $x, int $y) : ?Node
{
if (!isset($this->nodes[$y]) || !isset($this->nodes[$y][$x])) {
return null;
}
return $this->nodes[$y][$x];
}
/**
* Is node walkable"
*
* @param int $x X-Coordinate
* @param int $y Y-Coordinate
*
* @return bool
*
* @since 1.0.0
*/
public function isWalkable(int $x, int $y) : bool
{
return isset($this->nodes[$y]) && isset($this->nodes[$y][$x]) && $this->nodes[$y][$x]->isWalkable;
}
/**
* Get neighbors of node
*
* @param Node $node Node to get neighbors from
* @param int $movement Allowed movements
*
* @return Node[]
*
* @since 1.0.0
*/
public function getNeighbors(Node $node, int $movement) : array
{
$x = $node->getX();
$y = $node->getY();
$neighbors = [];
$s0 = false;
$s1 = false;
$s2 = false;
$s3 = false;
$d0 = false;
$d1 = false;
$d2 = false;
$d3 = false;
if ($this->isWalkable($x, $y - 1)) {
$neighbors[] = $this->getNode($x, $y - 1);
$s0 = true;
}
if ($this->isWalkable($x + 1, $y)) {
$neighbors[] = $this->getNode($x + 1, $y);
$s1 = true;
}
if ($this->isWalkable($x, $y + 1)) {
$neighbors[] = $this->getNode($x, $y + 1);
$s2 = true;
}
if ($this->isWalkable($x - 1, $y)) {
$neighbors[] = $this->getNode($x - 1, $y);
$s3 = true;
}
if ($movement === MovementType::STRAIGHT) {
/** @var Node[] $neighbors */
return $neighbors;
}
if ($movement === MovementType::DIAGONAL_NO_OBSTACLE) {
$d0 = $s3 && $s0;
$d1 = $s0 && $s1;
$d2 = $s1 && $s2;
$d3 = $s2 && $s3;
} elseif ($movement === MovementType::DIAGONAL_ONE_OBSTACLE) {
$d0 = $s3 || $s0;
$d1 = $s0 || $s1;
$d2 = $s1 || $s2;
$d3 = $s2 || $s3;
} elseif ($movement === MovementType::DIAGONAL) {
$d0 = true;
$d1 = true;
$d2 = true;
$d3 = true;
}
if ($d0 && $this->isWalkable($x - 1, $y - 1)) {
$neighbors[] = $this->getNode($x - 1, $y - 1);
}
if ($d1 && $this->isWalkable($x + 1, $y - 1)) {
$neighbors[] = $this->getNode($x + 1, $y - 1);
}
if ($d2 && $this->isWalkable($x + 1, $y + 1)) {
$neighbors[] = $this->getNode($x + 1, $y + 1);
}
if ($d3 && $this->isWalkable($x - 1, $y + 1)) {
$neighbors[] = $this->getNode($x - 1, $y + 1);
}
/** @var Node[] $neighbors */
return $neighbors;
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\PathFinding;
use phpOMS\Math\Topology\Metrics2D;
/**
* Node on grid.
*
* @package phpOMS\Algorithm\PathFinding
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class Heuristic
{
/**
* Calculate metric/distance between two nodes.
*
* @param array<string, int|float> $node1 Array with 'x' and 'y' coordinate
* @param array<string, int|float> $node2 Array with 'x' and 'y' coordinate
* @param int $heuristic Heuristic to use for calculation
*
* @return float
*
* @since 1.0.0
*/
public static function metric(array $node1, array $node2, int $heuristic) : float
{
if ($heuristic === HeuristicType::MANHATTAN) {
return Metrics2D::manhattan($node1, $node2);
} elseif ($heuristic === HeuristicType::EUCLIDEAN) {
return Metrics2D::euclidean($node1, $node2);
} elseif ($heuristic === HeuristicType::OCTILE) {
return Metrics2D::octile($node1, $node2);
} elseif ($heuristic === HeuristicType::MINKOWSKI) {
return Metrics2D::minkowski($node1, $node2, 1);
} elseif ($heuristic === HeuristicType::CANBERRA) {
return Metrics2D::canberra($node1, $node2);
} elseif ($heuristic === HeuristicType::BRAY_CURTIS) {
return Metrics2D::brayCurtis($node1, $node2);
}
return Metrics2D::chebyshev($node1, $node2);
}
}

View File

@ -0,0 +1,42 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\PathFinding;
use phpOMS\Stdlib\Base\Enum;
/**
* Heuristic type enum.
*
* @package phpOMS\Algorithm\PathFinding
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
abstract class HeuristicType extends Enum
{
public const MANHATTAN = 1;
public const EUCLIDEAN = 2;
public const OCTILE = 4;
public const CHEBYSHEV = 8;
public const MINKOWSKI = 16;
public const CANBERRA = 32;
public const BRAY_CURTIS = 64;
}

View File

@ -0,0 +1,230 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\PathFinding;
/**
* Node on grid.
*
* @package phpOMS\Algorithm\PathFinding
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class JumpPointNode extends Node
{
/**
* The g score is cost of the path
*
* @var float
* @since 1.0.0
*/
private float $g = 0.0;
/**
* The heuristic distance is the cost to the end node
*
* @var float
* @since 1.0.0
*/
private ?float $h = null;
/**
* The f score is defined as f(n) = g(n) + h(n)
*
* @var float
* @since 1.0.0
*/
private float $f = 0.0;
/**
* Define as checked node
*
* @var bool
* @since 1.0.0
*/
private bool $isClosed = false;
/**
* Define as potential candidate
*
* @var bool
* @since 1.0.0
*/
private bool $isOpened = false;
/**
* The node was already tested?
*
* @var bool
* @since 1.0.0
*/
private bool $isTested = false;
/**
* Is checked?
*
* @return bool
*
* @since 1.0.0
*/
public function isClosed() : bool
{
return $this->isClosed;
}
/**
* Is potential candidate
*
* @return bool
*
* @since 1.0.0
*/
public function isOpened() : bool
{
return $this->isOpened;
}
/**
* Is already tested
*
* @return bool
*
* @since 1.0.0
*/
public function isTested() : bool
{
return $this->isTested;
}
/**
* Set check status
*
* @param bool $isClosed Is closed
*
* @return void
*
* @since 1.0.0
*/
public function setClosed(bool $isClosed) : void
{
$this->isClosed = $isClosed;
}
/**
* Set potential candidate
*
* @param bool $isOpened Is potential candidate
*
* @return void
*
* @since 1.0.0
*/
public function setOpened(bool $isOpened) : void
{
$this->isOpened = $isOpened;
}
/**
* Set tested
*
* @param bool $isTested Node tested?
*
* @return void
*
* @since 1.0.0
*/
public function setTested(bool $isTested) : void
{
$this->isTested = $isTested;
}
/**
* Set the g score
*
* @param float $g G score
*
* @return void
*
* @since 1.0.0
*/
public function setG(float $g) : void
{
$this->g = $g;
}
/**
* Set the heuristic distance
*
* @param float $h H distance
*
* @return void
*
* @since 1.0.0
*/
public function setH(?float $h) : void
{
$this->h = $h;
}
/**
* Set the f score
*
* @param float $f F score
*
* @return void
*
* @since 1.0.0
*/
public function setF(float $f) : void
{
$this->f = $f;
}
/**
* Get the g score
*
* @return float
*
* @since 1.0.0
*/
public function getG() : float
{
return $this->g;
}
/**
* Get the heuristic distance
*
* @return float
*
* @since 1.0.0
*/
public function getH() : ?float
{
return $this->h;
}
/**
* Get the f score
*
* @return float
*
* @since 1.0.0
*/
public function getF() : float
{
return $this->f;
}
}

View File

@ -0,0 +1,731 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*
* Extended based on:
* MIT License
* (c) 2011-2012 Xueqiao Xu <xueqiaoxu@gmail.com>
* (c) PathFinding.js
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\PathFinding;
use phpOMS\Stdlib\Base\Heap;
/**
* Perform path finding.
*
* @package phpOMS\Algorithm\PathFinding
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class JumpPointSearch implements PathFinderInterface
{
/**
* {@inheritdoc}
*/
public static function findPath(
int $startX, int $startY,
int $endX, int $endY,
Grid $grid,
int $heuristic, int $movement
) : Path
{
/** @var null|JumpPointNode $startNode */
$startNode = $grid->getNode($startX, $startY);
/** @var null|JumpPointNode $endNode */
$endNode = $grid->getNode($endX, $endY);
if ($startNode === null || $endNode === null) {
return new Path($grid);
}
$startNode->setG(0.0);
$startNode->setF(0.0);
$startNode->setOpened(true);
$openList = new Heap(function($node1, $node2) {
return $node1->getF() - $node2->getF();
});
$openList->push($startNode);
$node = null;
while (!$openList->isEmpty()) {
$node = $openList->pop();
if ($node === null) {
break;
}
/** @var JumpPointNode $node */
$node->setClosed(true);
if ($node->isEqual($endNode)) {
break;
}
$openList = self::identifySuccessors($node, $grid, $heuristic, $movement, $endNode, $openList);
}
$path = new Path($grid);
while ($node !== null) {
$path->addNode($node);
$node = $node->parent;
}
return $path;
}
/**
* Find possible successor jump points
*
* @param JumpPointNode $node Node to find successor for
* @param Grid $grid Grid of the nodes
* @param int $heuristic Heuristic/metrics type for the distance calculation
* @param int $movement Movement type
* @param JumpPointNode $endNode End node to find path to
* @param Heap $openList Heap of open nodes
*
* @return Heap
*
* @since 1.0.0
*/
public static function identifySuccessors(JumpPointNode $node, Grid $grid, int $heuristic, int $movement, JumpPointNode $endNode, Heap $openList) : Heap
{
/** @var JumpPointNode[] $neighbors */
$neighbors = self::findNeighbors($node, $movement, $grid);
$neighborsLength = \count($neighbors);
for ($i = 0; $i < $neighborsLength; ++$i) {
$neighbor = $neighbors[$i];
if ($neighbor === null) {
continue;
}
$jumpPoint = self::jump($neighbor, $node, $endNode, $movement, $grid);
if ($jumpPoint === null || $jumpPoint->isClosed()) {
continue;
}
$d = Heuristic::metric($node->getCoordinates(), $jumpPoint->getCoordinates(), HeuristicType::OCTILE);
$ng = $node->getG() + $d;
if (!$jumpPoint->isOpened() || $ng < $jumpPoint->getG()) {
$jumpPoint->setG($ng);
$jumpPoint->setH($jumpPoint->getH() ?? Heuristic::metric($jumpPoint->getCoordinates(), $endNode->getCoordinates(), $heuristic));
$jumpPoint->setF($jumpPoint->getG() + $jumpPoint->getH());
$jumpPoint->parent = $node;
if (!$jumpPoint->isOpened()) {
$openList->push($jumpPoint);
$jumpPoint->setOpened(true);
} else {
$openList->update($jumpPoint);
}
}
}
return $openList;
}
/**
* Find neighbor of node
*
* @param JumpPointNode $node Node to find successor for
* @param int $movement Movement type
* @param Grid $grid Grid of the nodes
*
* @return Node[] Neighbors of node
*
* @since 1.0.0
*/
private static function findNeighbors(JumpPointNode $node, int $movement, Grid $grid) : array
{
if ($movement === MovementType::STRAIGHT) {
return self::findNeighborsStraight($node, $grid);
} elseif ($movement === MovementType::DIAGONAL) {
return self::findNeighborsDiagonal($node, $grid);
} elseif ($movement === MovementType::DIAGONAL_ONE_OBSTACLE) {
return self::findNeighborsDiagonalOneObstacle($node, $grid);
}
return self::findNeighborsDiagonalNoObstacle($node, $grid);
}
/**
* Find neighbor of node
*
* @param JumpPointNode $node Node to find successor for
* @param Grid $grid Grid of the nodes
*
* @return Node[] Neighbors of node
*
* @since 1.0.0
*/
private static function findNeighborsStraight(JumpPointNode $node, Grid $grid) : array
{
if ($node->parent === null) {
return $grid->getNeighbors($node, MovementType::STRAIGHT);
}
$x = $node->getX();
$y = $node->getY();
$px = $node->parent->getX();
$py = $node->parent->getY();
/** @var int $dx */
$dx = ($x - $px) / \max(\abs($x - $px), 1);
/** @var int $dy */
$dy = ($y - $py) / \max(\abs($y - $py), 1);
$neighbors = [];
if ($dx !== 0) {
if ($grid->isWalkable($x, $y - 1)) {
$neighbors[] = $grid->getNode($x, $y - 1);
}
if ($grid->isWalkable($x, $y + 1)) {
$neighbors[] = $grid->getNode($x, $y + 1);
}
if ($grid->isWalkable($x + $dx, $y)) {
$neighbors[] = $grid->getNode($x + $dx, $y);
}
} elseif ($dy !== 0) {
if ($grid->isWalkable($x - 1, $y)) {
$neighbors[] = $grid->getNode($x - 1, $y);
}
if ($grid->isWalkable($x + 1, $y)) {
$neighbors[] = $grid->getNode($x + 1, $y);
}
if ($grid->isWalkable($x, $y + $dy)) {
$neighbors[] = $grid->getNode($x, $y + $dy);
}
}
/** @var JumpPointNode[] $neighbors */
return $neighbors;
}
/**
* Find neighbor of node
*
* @param JumpPointNode $node Node to find successor for
* @param Grid $grid Grid of the nodes
*
* @return Node[] Neighbors of node
*
* @since 1.0.0
*/
private static function findNeighborsDiagonal(JumpPointNode $node, Grid $grid) : array
{
if ($node->parent === null) {
return $grid->getNeighbors($node, MovementType::DIAGONAL);
}
$x = $node->getX();
$y = $node->getY();
$px = $node->parent->getX();
$py = $node->parent->getY();
/** @var int $dx */
$dx = ($x - $px) / \max(\abs($x - $px), 1);
/** @var int $dy */
$dy = ($y - $py) / \max(\abs($y - $py), 1);
$neighbors = [];
if ($dx !== 0 && $dy !== 0) {
if ($grid->isWalkable($x, $y + $dy)) {
$neighbors[] = $grid->getNode($x, $y + $dy);
}
if ($grid->isWalkable($x + $dx, $y)) {
$neighbors[] = $grid->getNode($x + $dx, $y);
}
if ($grid->isWalkable($x + $dx, $y + $dy)) {
$neighbors[] = $grid->getNode($x + $dx, $y + $dy);
}
if (!$grid->isWalkable($x - $dx, $y)) {
$neighbors[] = $grid->getNode($x - $dx, $y + $dy);
}
if (!$grid->isWalkable($x, $y - $dy)) {
$neighbors[] = $grid->getNode($x + $dx, $y - $dy);
}
} elseif ($dx === 0) {
if ($grid->isWalkable($x, $y + $dy)) {
$neighbors[] = $grid->getNode($x, $y + $dy);
}
if (!$grid->isWalkable($x + 1, $y)) {
$neighbors[] = $grid->getNode($x + 1, $y + $dy);
}
if (!$grid->isWalkable($x - 1, $y)) {
$neighbors[] = $grid->getNode($x - 1, $y + $dy);
}
} else {
if ($grid->isWalkable($x + $dx, $y)) {
$neighbors[] = $grid->getNode($x + $dx, $y);
}
if (!$grid->isWalkable($x, $y + 1)) {
$neighbors[] = $grid->getNode($x + $dx, $y + 1);
}
if (!$grid->isWalkable($x, $y - 1)) {
$neighbors[] = $grid->getNode($x + $dx, $y - 1);
}
}
/** @var JumpPointNode[] $neighbors */
return $neighbors;
}
/**
* Find neighbor of node
*
* @param JumpPointNode $node Node to find successor for
* @param Grid $grid Grid of the nodes
*
* @return Node[] Neighbors of node
*
* @since 1.0.0
*/
private static function findNeighborsDiagonalOneObstacle(JumpPointNode $node, Grid $grid) : array
{
if ($node->parent === null) {
return $grid->getNeighbors($node, MovementType::DIAGONAL_ONE_OBSTACLE);
}
$x = $node->getX();
$y = $node->getY();
$px = $node->parent->getX();
$py = $node->parent->getY();
/** @var int $dx */
$dx = ($x - $px) / \max(\abs($x - $px), 1);
/** @var int $dy */
$dy = ($y - $py) / \max(\abs($y - $py), 1);
$neighbors = [];
if ($dx !== 0 && $dy !== 0) {
if ($grid->isWalkable($x, $y + $dy)) {
$neighbors[] = $grid->getNode($x, $y + $dy);
}
if ($grid->isWalkable($x + $dx, $y)) {
$neighbors[] = $grid->getNode($x + $dx, $y);
}
if ($grid->isWalkable($x, $y + $dy) || $grid->isWalkable($x + $dx, $y)) {
$neighbors[] = $grid->getNode($x + $dx, $y + $dy);
}
if (!$grid->isWalkable($x - $dx, $y) && $grid->isWalkable($x, $y + $dy)) {
$neighbors[] = $grid->getNode($x - $dx, $y + $dy);
}
if (!$grid->isWalkable($x, $y - $dy) && $grid->isWalkable($x + $dx, $y)) {
$neighbors[] = $grid->getNode($x + $dx, $y - $dy);
}
} elseif ($dx === 0) {
if ($grid->isWalkable($x, $y + $dy)) {
$neighbors[] = $grid->getNode($x, $y + $dy);
if (!$grid->isWalkable($x + 1, $y)) {
$neighbors[] = $grid->getNode($x + 1, $y + $dy);
}
if (!$grid->isWalkable($x - 1, $y)) {
$neighbors[] = $grid->getNode($x - 1, $y + $dy);
}
}
} elseif ($grid->isWalkable($x + $dx, $y)) {
$neighbors[] = $grid->getNode($x + $dx, $y);
if (!$grid->isWalkable($x, $y + 1)) {
$neighbors[] = $grid->getNode($x + $dx, $y + 1);
}
if (!$grid->isWalkable($x, $y - 1)) {
$neighbors[] = $grid->getNode($x + $dx, $y - 1);
}
}
/** @var JumpPointNode[] $neighbors */
return $neighbors;
}
/**
* Find neighbor of node
*
* @param JumpPointNode $node Node to find successor for
* @param Grid $grid Grid of the nodes
*
* @return Node[] Neighbors of node
*
* @since 1.0.0
*/
private static function findNeighborsDiagonalNoObstacle(JumpPointNode $node, Grid $grid) : array
{
if ($node->parent === null) {
return $grid->getNeighbors($node, MovementType::DIAGONAL_NO_OBSTACLE);
}
$x = $node->getX();
$y = $node->getY();
$px = $node->parent->getX();
$py = $node->parent->getY();
/** @var int $dx */
$dx = ($x - $px) / \max(\abs($x - $px), 1);
/** @var int $dy */
$dy = ($y - $py) / \max(\abs($y - $py), 1);
$neighbors = [];
if ($dx !== 0 && $dy !== 0) {
if ($grid->isWalkable($x, $y + $dy)) {
$neighbors[] = $grid->getNode($x, $y + $dy);
}
if ($grid->isWalkable($x + $dx, $y)) {
$neighbors[] = $grid->getNode($x + $dx, $y);
}
if ($grid->isWalkable($x, $y + $dy) || $grid->isWalkable($x + $dx, $y)) {
$neighbors[] = $grid->getNode($x + $dx, $y + $dy);
}
} elseif ($dx !== 0 && $dy === 0) {
$isNextWalkable = $grid->isWalkable($x + $dx, $y);
$isTopWalkable = $grid->isWalkable($x, $y + 1);
$isBottomWalkable = $grid->isWalkable($x, $y - 1);
if ($isNextWalkable) {
$neighbors[] = $grid->getNode($x + $dx, $y);
if ($isTopWalkable) {
$neighbors[] = $grid->getNode($x + $dx, $y + 1);
}
if ($isBottomWalkable) {
$neighbors[] = $grid->getNode($x + $dx, $y - 1);
}
}
if ($isTopWalkable) {
$neighbors[] = $grid->getNode($x, $y + 1);
}
if ($isBottomWalkable) {
$neighbors[] = $grid->getNode($x, $y - 1);
}
} elseif ($dx === 0 && $dy !== 0) {
$isNextWalkable = $grid->isWalkable($x, $y + $dy);
$isRightWalkable = $grid->isWalkable($x + 1, $y);
$isLeftWalkable = $grid->isWalkable($x - 1, $y);
if ($isNextWalkable) {
$neighbors[] = $grid->getNode($x, $y + $dy);
if ($isRightWalkable) {
$neighbors[] = $grid->getNode($x + 1, $y + $dy);
}
if ($isLeftWalkable) {
$neighbors[] = $grid->getNode($x - 1, $y + $dy);
}
}
if ($isRightWalkable) {
$neighbors[] = $grid->getNode($x + 1, $y);
}
if ($isLeftWalkable) {
$neighbors[] = $grid->getNode($x - 1, $y);
}
}
/** @var JumpPointNode[] $neighbors */
return $neighbors;
}
/**
* Find next jump point
*
* @param null|JumpPointNode $node Node to find jump point from
* @param null|JumpPointNode $pNode Parent node
* @param JumpPointNode $endNode End node to find path to
* @param int $movement Movement type
* @param Grid $grid Grid of the nodes
*
* @return null|JumpPointNode
*
* @since 1.0.0
*/
private static function jump(?JumpPointNode $node, ?JumpPointNode $pNode, JumpPointNode $endNode, int $movement, Grid $grid) : ?JumpPointNode
{
if ($movement === MovementType::STRAIGHT) {
return self::jumpStraight($node, $pNode, $endNode, $grid);
} elseif ($movement === MovementType::DIAGONAL) {
return self::jumpDiagonal($node, $pNode, $endNode, $grid);
} elseif ($movement === MovementType::DIAGONAL_ONE_OBSTACLE) {
return self::jumpDiagonalOneObstacle($node, $pNode, $endNode, $grid);
}
return self::jumpDiagonalNoObstacle($node, $pNode, $endNode, $grid);
}
/**
* Find next jump point
*
* @param null|JumpPointNode $node Node to find jump point from
* @param null|JumpPointNode $pNode Parent node
* @param JumpPointNode $endNode End node to find path to
* @param Grid $grid Grid of the nodes
*
* @return null|JumpPointNode
*
* @throws \Exception
*
* @since 1.0.0
*/
private static function jumpStraight(?JumpPointNode $node, ?JumpPointNode $pNode, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode
{
if ($node === null || $pNode === null || !$node->isWalkable) {
return null;
}
$x = $node->getX();
$y = $node->getY();
$dx = $x - $pNode->getX();
$dy = $y - $pNode->getY();
// not always necessary but might be important for the future
$node->setTested(true);
if ($node->isEqual($endNode)) {
return $node;
}
if ($dx !== 0) {
if (($grid->isWalkable($x, $y - 1) && !$grid->isWalkable($x - $dx, $y - 1))
|| ($grid->isWalkable($x, $y + 1) && !$grid->isWalkable($x - $dx, $y + 1))
) {
return $node;
}
} elseif ($dy !== 0) {
if (($grid->isWalkable($x - 1, $y) && !$grid->isWalkable($x - 1, $y - $dy))
|| ($grid->isWalkable($x + 1, $y) && !$grid->isWalkable($x + 1, $y - $dy))
) {
return $node;
}
if (self::jumpStraight($grid->getNode($x + 1, $y), $node, $endNode, $grid) !== null
|| self::jumpStraight($grid->getNode($x - 1, $y), $node, $endNode, $grid) !== null
) {
return $node;
}
} else {
throw new \Exception('invalid movement'); // @codeCoverageIgnore
}
return self::jumpStraight($grid->getNode($x + $dx, $y + $dy), $node, $endNode, $grid);
}
/**
* Find next jump point
*
* @param null|JumpPointNode $node Node to find jump point from
* @param null|JumpPointNode $pNode Parent node
* @param JumpPointNode $endNode End node to find path to
* @param Grid $grid Grid of the nodes
*
* @return null|JumpPointNode
*
* @since 1.0.0
*/
private static function jumpDiagonal(?JumpPointNode $node, ?JumpPointNode $pNode, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode
{
if ($node === null || $pNode === null || !$node->isWalkable) {
return null;
}
$x = $node->getX();
$y = $node->getY();
$dx = $x - $pNode->getX();
$dy = $y - $pNode->getY();
// not always necessary but might be important for the future
$node->setTested(true);
if ($node->isEqual($endNode)) {
return $node;
}
if ($dx !== 0 && $dy !== 0) {
if (($grid->isWalkable($x - $dx, $y + $dy) && !$grid->isWalkable($x - $dx, $y))
|| ($grid->isWalkable($x + $dx, $y - $dy) && !$grid->isWalkable($x, $y - $dy))
) {
return $node;
}
if (self::jumpDiagonal($grid->getNode($x + $dx, $y), $node, $endNode, $grid) !== null
|| self::jumpDiagonal($grid->getNode($x, $y + $dy), $node, $endNode, $grid) !== null
) {
return $node;
}
} elseif ($dx !== 0) {
if (($grid->isWalkable($x + $dx, $y + 1) && !$grid->isWalkable($x, $y + 1))
|| ($grid->isWalkable($x + $dx, $y - 1) && !$grid->isWalkable($x, $y - 1))
) {
return $node;
}
} elseif (($grid->isWalkable($x + 1, $y + $dy) && !$grid->isWalkable($x + 1, $y))
|| ($grid->isWalkable($x - 1, $y + $dy) && !$grid->isWalkable($x - 1, $y))
) {
return $node;
}
return self::jumpDiagonal($grid->getNode($x + $dx, $y + $dy), $node, $endNode, $grid);
}
/**
* Find next jump point
*
* @param null|JumpPointNode $node Node to find jump point from
* @param null|JumpPointNode $pNode Parent node
* @param JumpPointNode $endNode End node to find path to
* @param Grid $grid Grid of the nodes
*
* @return null|JumpPointNode
*
* @since 1.0.0
*/
private static function jumpDiagonalOneObstacle(?JumpPointNode $node, ?JumpPointNode $pNode, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode
{
if ($node === null || $pNode === null || !$node->isWalkable) {
return null;
}
$x = $node->getX();
$y = $node->getY();
$dx = $x - $pNode->getX();
$dy = $y - $pNode->getY();
// not always necessary but might be important for the future
$node->setTested(true);
if ($node->isEqual($endNode)) {
return $node;
}
if ($dx !== 0 && $dy !== 0) {
if (($grid->isWalkable($x - $dx, $y + $dy) && !$grid->isWalkable($x - $dx, $y))
|| ($grid->isWalkable($x + $dx, $y - $dy) && !$grid->isWalkable($x, $y - $dy))
) {
return $node;
}
if (self::jumpDiagonalOneObstacle($grid->getNode($x + $dx, $y), $node, $endNode, $grid) !== null
|| self::jumpDiagonalOneObstacle($grid->getNode($x, $y + $dy), $node, $endNode, $grid) !== null
) {
return $node;
}
} elseif ($dx !== 0) {
if (($grid->isWalkable($x + $dx, $y + 1) && !$grid->isWalkable($x, $y + 1))
|| ($grid->isWalkable($x + $dx, $y - 1) && !$grid->isWalkable($x, $y - 1))
) {
return $node;
}
} elseif (($grid->isWalkable($x + 1, $y + $dy) && !$grid->isWalkable($x + 1, $y))
|| ($grid->isWalkable($x - 1, $y + $dy) && !$grid->isWalkable($x - 1, $y))
) {
return $node;
}
if ($grid->isWalkable($x + $dx, $y) || $grid->isWalkable($x, $y + $dy)) {
return self::jumpDiagonalOneObstacle($grid->getNode($x + $dx, $y + $dy), $node, $endNode, $grid);
}
return null;
}
/**
* Find next jump point
*
* @param null|JumpPointNode $node Node to find jump point from
* @param null|JumpPointNode $pNode Parent node
* @param JumpPointNode $endNode End node to find path to
* @param Grid $grid Grid of the nodes
*
* @return null|JumpPointNode
*
* @since 1.0.0
*/
private static function jumpDiagonalNoObstacle(?JumpPointNode $node, ?JumpPointNode $pNode, JumpPointNode $endNode, Grid $grid) : ?JumpPointNode
{
if ($node === null || $pNode === null || !$node->isWalkable) {
return null;
}
$x = $node->getX();
$y = $node->getY();
$dx = $x - $pNode->getX();
$dy = $y - $pNode->getY();
// not always necessary but might be important for the future
$node->setTested(true);
if ($node->isEqual($endNode)) {
return $node;
}
if ($dx !== 0 && $dy !== 0) {
if (self::jumpDiagonalNoObstacle($grid->getNode($x + $dx, $y), $node, $endNode, $grid) !== null
|| self::jumpDiagonalNoObstacle($grid->getNode($x, $y + $dy), $node, $endNode, $grid) !== null
) {
return $node;
}
} elseif ($dx !== 0) {
if (($grid->isWalkable($x, $y - 1) && !$grid->isWalkable($x - $dx, $y - 1))
|| ($grid->isWalkable($x, $y + 1) && !$grid->isWalkable($x - $dx, $y + 1))
) {
return $node;
}
} elseif ($dy !== 0) {
if (($grid->isWalkable($x - 1, $y) && !$grid->isWalkable($x - 1, $y - $dy))
|| ($grid->isWalkable($x + 1, $y) && !$grid->isWalkable($x + 1, $y - $dy))
) {
return $node;
}
}
if ($grid->isWalkable($x + $dx, $y) || $grid->isWalkable($x, $y + $dy)) {
return self::jumpDiagonalNoObstacle($grid->getNode($x + $dx, $y + $dy), $node, $endNode, $grid);
}
return null;
}
}

View File

@ -0,0 +1,36 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\PathFinding;
use phpOMS\Stdlib\Base\Enum;
/**
* Movement type enum.
*
* @package phpOMS\Algorithm\PathFinding
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
abstract class MovementType extends Enum
{
public const DIAGONAL = 1;
public const STRAIGHT = 2;
public const DIAGONAL_ONE_OBSTACLE = 4;
public const DIAGONAL_NO_OBSTACLE = 8;
}

148
Algorithm/PathFinding/Node.php Executable file
View File

@ -0,0 +1,148 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\PathFinding;
use phpOMS\Stdlib\Base\HeapItemInterface;
/**
* Node on grid.
*
* @package phpOMS\Algorithm\PathFinding
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Node implements HeapItemInterface
{
/**
* X-Coordinate.
*
* @var int
* @since 1.0.0
*/
private int $x = 0;
/**
* Y-Coordinate.
*
* @var int
* @since 1.0.0
*/
private int $y = 0;
/**
* Cost of the node.
*
* @var float
* @since 1.0.0
*/
private float $weight = 1.0;
/**
* Can be walked?
*
* @var bool
* @since 1.0.0
*/
public bool $isWalkable = true;
/**
* Parent node.
*
* @var null|Node
* @since 1.0.0
*/
public ?Node $parent = null;
/**
* Constructor.
*
* @param int $x X-Coordinate
* @param int $y Y-Coordinate
* @param float $weight Cost of reaching this node
* @param bool $isWalkable Can be walked on?
*
* @since 1.0.0
*/
public function __construct(int $x, int $y, float $weight = 1.0, bool $isWalkable = true)
{
$this->x = $x;
$this->y = $y;
$this->weight = $weight;
$this->isWalkable = $isWalkable;
}
/**
* Get the cost to walk on this node
*
* @return float
*
* @since 1.0.0
*/
public function getWeight() : float
{
return $this->weight;
}
/**
* Get x-coordinate
*
* @return int
*
* @since 1.0.0
*/
public function getX() : int
{
return $this->x;
}
/**
* Get y-coordinate
*
* @return int
*
* @since 1.0.0
*/
public function getY() : int
{
return $this->y;
}
/**
* Is node equal to another node?
*
* @param Node $node Node to compare to
*
* @return bool
*
* @since 1.0.0
*/
public function isEqual(HeapItemInterface $node) : bool
{
return $this->x === $node->getX() && $this->y === $node->getY();
}
/**
* Get the coordinates of this node.
*
* @return array<string, int> ['x' => ?, 'y' => ?]
*
* @since 1.0.0
*/
public function getCoordinates() : array
{
return ['x' => $this->x, 'y' => $this->y];
}
}

View File

@ -0,0 +1,27 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\PathFinding;
/**
* Null node.
*
* @package phpOMS\Algorithm\PathFinding
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class NullJumpPointNode extends JumpPointNode
{
}

View File

@ -0,0 +1,27 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\PathFinding;
/**
* Null node.
*
* @package phpOMS\Algorithm\PathFinding
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class NullNode extends Node
{
}

210
Algorithm/PathFinding/Path.php Executable file
View File

@ -0,0 +1,210 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*
* Extended based on:
* MIT License
* (c) 2011-2012 Xueqiao Xu <xueqiaoxu@gmail.com>
* (c) PathFinding.js
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\PathFinding;
/**
* Path in grids.
*
* @package phpOMS\Algorithm\PathFinding
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
class Path
{
/**
* Nodes in the path
*
* @var Node[]
* @since 1.0.0
*/
public array $nodes = [];
/**
* Grid this path belongs to
*
* @var Grid
* @since 1.0.0
*/
private Grid $grid;
/**
* Nodes in the path
*
* @var Node[]
* @since 1.0.0
*/
private array $expandedNodes = [];
/**
* Constructor.
*
* @param Grid $grid Grid this path belongs to
*
* @since 1.0.0
*/
public function __construct(Grid $grid)
{
$this->grid = $grid;
}
/**
* Add node to the path
*
* @param Node $node Node
*
* @return void
*
* @since 1.0.0
*/
public function addNode(Node $node) : void
{
$this->nodes[] = $node;
}
/**
* Get the path length (euclidean)
*
* @return float
*
* @since 1.0.0
*/
public function getLength() : float
{
$n = \count($this->nodes);
$dist = 0.0;
for ($i = 1; $i < $n; ++$i) {
$dx = $this->nodes[$i - 1]->getX() - $this->nodes[$i]->getX();
$dy = $this->nodes[$i - 1]->getY() - $this->nodes[$i]->getY();
$dist += \sqrt($dx * $dx + $dy * $dy);
}
return $dist;
}
/**
* Get the incomplete node path
*
* @return Node[]
*
* @since 1.0.0
*/
public function getPath() : array
{
return $this->nodes;
}
/**
* Get the complete node path
*
* The path may only contain the jump points or pivot points.
* In order to get every node it needs to be expanded.
*
* @return Node[]
*
* @since 1.0.0
*/
public function expandPath() : array
{
if (empty($this->expandedNodes)) {
//$reverse = \array_reverse($this->nodes);
$reverse = $this->nodes;
$length = \count($reverse);
if ($length < 2) {
return $reverse;
}
$expanded = [];
for ($i = 0; $i < $length - 1; ++$i) {
$coord0 = $reverse[$i];
$coord1 = $reverse[$i + 1];
$interpolated = $this->interpolate($coord0, $coord1);
$expanded = \array_merge($expanded, $interpolated);
}
$expanded[] = $reverse[$length - 1];
$this->expandedNodes = $expanded;
}
return $this->expandedNodes;
}
/**
* Find nodes in between two nodes.
*
* The path may only contain the jump points or pivot points.
* In order to get every node it needs to be expanded.
*
* @param Node $node1 Node
* @param Node $node2 Node
*
* @return Node[]
*
* @since 1.0.0
*/
private function interpolate(Node $node1, Node $node2) : array
{
$dx = \abs($node2->getX() - $node1->getX());
$dy = \abs($node2->getY() - $node1->getY());
$sx = ($node1->getX() < $node2->getX()) ? 1 : -1;
$sy = ($node1->getY() < $node2->getY()) ? 1 : -1;
$node = $node1;
$err = $dx - $dy;
$x0 = $node->getX();
$y0 = $node->getY();
$line = [];
while (true) {
if ($node->getX() === $node2->getX() && $node->getY() === $node2->getY()) {
break;
}
$line[] = $node;
$e2 = 2 * $err;
if ($e2 > -$dy) {
$err -= $dy;
$x0 += $sx;
}
if ($e2 < $dx) {
$err += $dx;
$y0 += $sy;
}
$node = $this->grid->getNode($x0, $y0);
if ($node === null) {
break; // @codeCoverageIgnore
}
}
return $line;
}
}

View File

@ -0,0 +1,48 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\PathFinding
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\PathFinding;
/**
* Path finder interface
*
* @package phpOMS\Algorithm\PathFinding
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
interface PathFinderInterface
{
/**
* Find path from one point to another
*
* @param int $startX Start point X-Coordinate
* @param int $startY Start point Y-Coordinate
* @param int $endX End point X-Coordinate
* @param int $endY End point Y-Coordinate
* @param Grid $grid Grid with the walkable points
* @param int $heuristic Heuristic algorithm to use in order to calculate the distance for a good path
* @param int $movement Allowed movement (e.g. straight, diagonal, ...)
*
* @return Path
*
* @since 1.0.0
*/
public static function findPath(
int $startX, int $startY,
int $endX, int $endY,
Grid $grid,
int $heuristic, int $movement
) : Path;
}

View File

@ -0,0 +1,85 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Rating
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Rating;
/**
* Calculate rating strength using the Bradley Terry model
*
* @package phpOMS\Algorithm\Rating
* @license OMS License 2.0
* @link https://jingga.app
* @see https://en.wikipedia.org/wiki/Bradley%E2%80%93Terry_model
* @since 1.0.0
*/
final class BradleyTerry
{
/**
* Rate the strongest to the weakest team based on historic performances (wins/losses)
*
* The following example contains match results (matrix) of teams A-D facing each other (each point is a victory).
* @example rating(
* [
* 'A' => ['A' => 0, 'B' => 2, 'C' => 0, 'D' => 1],
* 'B' => ['A' => 3, 'B' => 0, 'C' => 5, 'D' => 0],
* 'C' => ['A' => 0, 'B' => 3, 'C' => 0, 'D' => 1],
* 'D' => ['A' => 4, 'B' => 0, 'C' => 3, 'D' => 0],
* ],
* 10
* ) // [0.640, 1.043, 0.660, 2.270] -> D is strongest
*
* @param array[] $history Historic results
* @param int $iterations Iterations for estimation
*
* @return float[] Array of "strength" scores (highest = strongest)
*
* @since 1.0.0
*/
public function rating(array $history, int $iterations = 20) : array
{
$keys = \array_keys($history);
$pOld = [];
foreach ($keys as $key) {
$pOld[$key] = 1;
}
$p = $pOld;
for ($i = 0; $i < $iterations; ++$i) {
foreach ($history as $idx => $row) {
$W = \array_sum($row);
$d = 0;
foreach ($history as $idx2 => $_) {
if ($idx === $idx2) {
continue;
}
$d += ($history[$idx][$idx2] + $history[$idx2][$idx])
/ ($pOld[$idx] + $pOld[$idx2]);
}
$p[$idx] = $W / $d;
}
$norm = \array_sum($p);
foreach ($p as $idx => $_) {
$p[$idx] /= $norm;
}
$pOld = $p;
}
return $p;
}
}

110
Algorithm/Rating/Elo.php Normal file
View File

@ -0,0 +1,110 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Rating
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Rating;
/**
* Elo rating calculation using Elo rating
*
* @package phpOMS\Algorithm\Rating
* @license OMS License 2.0
* @link https://jingga.app
* @see https://en.wikipedia.org/wiki/Elo_rating_system
* @since 1.0.0
*/
final class Elo
{
/**
* ELO change rate
*
* @var int
* @since 1.0.0
*/
public int $K = 32;
/**
* Default elo to use for new players
*
* @var int
* @since 1.0.0
*/
public int $DEFAULT_ELO = 1500;
/**
* Lowest elo allowed
*
* @var int
* @since 1.0.0
*/
public int $MIN_ELO = 100;
/**
* Calculate the elo rating
*
* @param int $elo Current player elo
* @param int[] $oElo Current elo of all opponents
* @param float[] $s Match results against the opponents (1 = victor, 0 = loss, 0.5 = draw)
*
* @return array{elo:int}
*
* @since 1.0.0
*/
public function rating(int $elo, array $oElo, array $s) : array
{
$eloNew = $elo;
foreach ($oElo as $idx => $o) {
$expected = 1 / (1 + 10 ** (($o - $elo) / 400));
$r = $this->K * ($s[$idx] - $expected);
$eloNew += (int) \round($r);
}
return [
'elo' => (int) \max($eloNew, $this->MIN_ELO),
];
}
/**
* Calculate an approximated win probability based on elo points.
*
* @param int $elo1 Elo of the player we want to calculate the win probability for
* @param int $elo2 Opponent elo
* @param bool $canDraw Is a draw possible?
*
* @return float
*
* @since 1.0.0
*/
public function winProbability(int $elo1, int $elo2, bool $canDraw = false) : float
{
return $canDraw
? -1.0 // @todo implement
: 1 / (1 + \pow(10, ($elo2 - $elo1) / 400));
}
/**
* Calculate an approximated draw probability based on elo points.
*
* @param int $elo1 Elo of the player we want to calculate the win probability for
* @param int $elo2 Opponent elo
*
* @return float
*
* @since 1.0.0
*/
public function drawProbability(int $elo1, int $elo2) : float
{
return -1.0; // @todo implement
}
}

View File

@ -0,0 +1,171 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Rating
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Rating;
/**
* Elo rating calculation using Glicko-1
*
* @package phpOMS\Algorithm\Rating
* @license OMS License 2.0
* @link https://jingga.app
* @see https://en.wikipedia.org/wiki/Glicko_rating_system
* @see http://www.glicko.net/glicko/glicko.pdf
* @since 1.0.0
*/
final class Glicko1
{
/**
* Helper constant
*
* @latex Q = ln(10) / 400
*
* @var int
* @since 1.0.0
*/
private const Q = 0.00575646273;
/**
* Default elo to use for new players
*
* @var int
* @since 1.0.0
*/
public int $DEFAULT_ELO = 1500;
/**
* Default rd to use for new players
*
* @var int
* @since 1.0.0
*/
public int $DEFAULT_RD = 350;
/**
* C (constant) for RD caclulation
*
* This is used to adjust the RD value based on the time from the last time a player played a match
*
* @latex RD = min\left(\sqrt{RD_0^2 + c^2t}, 350\right)
*
* @see calculateC();
*
* @var float
* @since 1.0.0
*/
public float $DEFAULT_C = 34.6;
/**
* Lowest elo allowed
*
* @var int
* @since 1.0.0
*/
public int $MIN_ELO = 100;
/**
* Lowest rd allowed
*
* @example 50 means that the player rating is probably between -100 / +100 of the current rating
*
* @var int
* @since 1.0.0
*/
public int $MIN_RD = 50;
/**
* Calculate the C value.
*
* This is only necessary if you change the DEFAULT_RD, want a different rating period or have significantly different average RD values.
*
* @param int $ratingPeriods Time without matches until the RD returns to the default RD
* @param int $avgRD Average RD
*
* @return void
*
* @since 1.0.0
*/
public function calculateC(int $ratingPeriods = 100, int $avgRD = 50) : void
{
$this->DEFAULT_C = \sqrt(($this->DEFAULT_RD ** 2 - $avgRD ** 2) / $ratingPeriods);
}
/**
* Calculate the glicko-1 elo
*
* @param int $elo Current player "elo"
* @param int $rdOld Current player deviation (RD)
* @param int $lastMatchDate Last match date used to calculate the time difference (can be days, months, ... depending on your match interval)
* @param int $matchDate Match date (usually day)
* @param int[] $oElo Opponent "elo"
* @param float[] $s Match results (1 = victor, 0 = loss, 0.5 = draw)
* @param int[] $oRd Opponent deviation (RD)
*
* @return array{elo:int, rd:int}
*
* @since 1.0.0
*/
public function rating(
int $elo = 1500,
int $rdOld = 50,
int $lastMatchDate = 0,
int $matchDate = 0,
array $oElo = [],
array $s = [],
array $oRd = []
) : array
{
// Step 1:
$E = [];
$gRD = [];
$RD = \min(
350,
\max(
\sqrt(
$rdOld * $rdOld
+ $this->DEFAULT_C * $this->DEFAULT_C * \max(0, $matchDate - $lastMatchDate)
),
$this->MIN_RD
)
);
// Step 2:
foreach ($oElo as $id => $e) {
$gRD_t = 1 / (\sqrt(1 + 3 * self::Q * self::Q * $oRd[$id] * $oRd[$id] / (\M_PI * \M_PI)));
$gRD[$id] = $gRD_t;
$E[$id] = 1 / (1 + \pow(10, $gRD_t * ($elo - $e) / -400));
}
$d = 0;
foreach ($E as $id => $_) {
$d += $gRD[$id] * $gRD[$id] * $E[$id] * (1 - $E[$id]);
}
$d2 = 1 / (self::Q * self::Q * $d);
$r = 0;
foreach ($E as $id => $_) {
$r += $gRD[$id] * ($s[$id] - $E[$id]);
}
$r = $elo + self::Q / (1 / ($RD * $RD) + 1 / $d2) * $r;
// Step 3:
$RD_ = \sqrt(1 / (1 / ($RD * $RD) + 1 / $d2));
return [
'elo' => (int) \max((int) $r, $this->MIN_ELO),
'rd' => (int) \max($RD_, $this->MIN_RD),
];
}
}

View File

@ -0,0 +1,179 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Rating
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Rating;
use phpOMS\Math\Solver\Root\Bisection;
/**
* Elo rating calculation using Glicko-2
*
* @package phpOMS\Algorithm\Rating
* @license OMS License 2.0
* @link https://jingga.app
* @see https://en.wikipedia.org/wiki/Glicko_rating_system
* @see http://www.glicko.net/glicko/glicko2.pdf
* @since 1.0.0
*/
final class Glicko2
{
/**
* Glicko scale factor
*
* @latex Q = 400 / ln(10)
*
* @var int
* @since 1.0.0
*/
private const Q = 173.7177927613;
/**
* Constraint for the volatility over time (smaller = stronger constraint)
*
* @var float
* @since 1.0.0
*/
public float $tau = 0.5;
/**
* Default elo to use for new players
*
* @var int
* @since 1.0.0
*/
public int $DEFAULT_ELO = 1500;
/**
* Default rd to use for new players
*
* @var int
* @since 1.0.0
*/
public int $DEFAULT_RD = 350;
/**
* Valatility (sigma)
*
* Expected flactuation = how erratic is the player's performance
*
* @var float
* @since 1.0.0
*/
public float $DEFAULT_VOLATILITY = 0.06;
/**
* Lowest elo allowed
*
* @var int
* @since 1.0.0
*/
public int $MIN_ELO = 100;
/**
* Lowest rd allowed
*
* @example 50 means that the player rating is probably between -100 / +100 of the current rating
*
* @var int
* @since 1.0.0
*/
public int $MIN_RD = 50;
/**
* Calculate the glicko-2 elo
*
* @example $glicko->elo(1500, 200, 0.06, [1,0,0], [1400,1550,1700], [30,100,300]) // 1464, 151, 0.059
*
* @param int $elo Current player "elo"
* @param int $rdOld Current player deviation (RD)
* @param float $volOld Last match date used to calculate the time difference (can be days, months, ... depending on your match interval)
* @param int[] $oElo Opponent "elo"
* @param float[] $s Match results (1 = victor, 0 = loss, 0.5 = draw)
* @param int[] $oRd Opponent deviation (RD)
*
* @return array{elo:int, rd:int, vol:float}
*
* @since 1.0.0
*/
public function rating(
int $elo = 1500,
int $rdOld = 50,
float $volOld = 0.06,
array $oElo = [],
array $s = [],
array $oRd = []
) : array
{
$tau = $this->tau;
// Step 0:
$rdOld /= self::Q;
$elo = ($elo - $this->DEFAULT_ELO) / self::Q;
foreach ($oElo as $idx => $value) {
$oElo[$idx] = ($value - $this->DEFAULT_ELO) / self::Q;
}
foreach ($oRd as $idx => $value) {
$oRd[$idx] = $value / self::Q;
}
// Step 1:
$g = [];
foreach ($oRd as $idx => $rd) {
$g[$idx] = 1 / \sqrt(1 + 3 * $rd * $rd / (\M_PI * \M_PI));
}
$E = [];
foreach ($oElo as $idx => $oe) {
$E[$idx] = 1 / (1 + \exp(-$g[$idx] * ($elo - $oe)));
}
$v = 0;
foreach ($g as $idx => $t) {
$v += $t * $t * $E[$idx] * (1 - $E[$idx]);
}
$v = 1 / $v;
$tDelta = 0;
foreach ($g as $idx => $t) {
$tDelta += $t * ($s[$idx] - $E[$idx]);
}
$Delta = $v * $tDelta;
// Step 2:
$fn = function($x) use ($Delta, $rdOld, $v, $tau, $volOld)
{
return 0.5 * (\exp($x) * ($Delta ** 2 - $rdOld ** 2 - $v - \exp($x))) / (($rdOld ** 2 + $v + \exp($x)) ** 2)
- ($x - \log($volOld ** 2)) / ($tau ** 2);
};
$root = Bisection::root($fn, -100, 100, 1000);
$vol = \exp($root / 2);
// Step 3:
$RD = 1 / \sqrt(1 / ($rdOld ** 2 + $vol ** 2) + 1 / $v);
$r = $elo + $RD ** 2 * $tDelta;
// Undo step 0:
$RD = self::Q * $RD;
$r = self::Q * $r + $this->DEFAULT_ELO;
return [
'elo' => (int) \max($r, $this->MIN_ELO),
'rd' => (int) \max($RD, $this->MIN_RD),
'vol' => $vol,
];
}
}

View File

@ -0,0 +1,290 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Rating
* @copyright Microsoft
* @license This algorithm may be patented by Microsoft, verify and acquire a license if necessary
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Rating;
use phpOMS\Math\Stochastic\Distribution\NormalDistribution;
/**
* Elo rating calculation using Elo rating
*
* @package phpOMS\Algorithm\Rating
* @license OMS License 2.0
* @link https://jingga.app
* @see https://www.moserware.com/assets/computing-your-skill/The%20Math%20Behind%20TrueSkill.pdf
* @since 1.0.0
*
* @todo Implement https://github.com/sublee/trueskill/blob/master/trueskill/__init__.py
* https://github.com/Karaka-Management/phpOMS/issues/337
*/
// phpcs:ignoreFile
class TrueSkill
{
public const DEFAULT_MU = 25;
public const DEFAULT_SIGMA = 25 / 3;
public const DEFAULT_BETA = 25 / 3 / 2;
public const DEFAULT_TAU = 25 / 3 / 100;
public const DEFAULT_DRAW_PROBABILITY = 0.1;
private float $mu = 0.0;
private float $sigma = 0.0;
private float $beta = 0.0;
private float $tau = 0.0;
private float $drawProbability = 0.0;
/**
* Constructor.
*
* @param null|float $mu Mu
* @param null|float $sigma Sigma
* @param null|float $beta Beta
* @param null|float $tau Tau
* @param null|float $drawProbability Draw probability
*
* @since 1.0.0
*/
public function __construct(
?float $mu = null,
?float $sigma = null,
?float $beta = null,
?float $tau = null,
?float $drawProbability = null)
{
$this->mu = $mu ?? self::DEFAULT_MU;
$this->sigma = $sigma ?? self::DEFAULT_SIGMA;
$this->beta = $beta ?? self::DEFAULT_BETA;
$this->tau = $tau ?? self::DEFAULT_TAU;
$this->drawProbability = $drawProbability ?? self::DEFAULT_DRAW_PROBABILITY;
}
/**
* Calculate win probability
*
* @param array $team1 Team 1
* @param array $team2 Team 2
* @param float $drawMargin Draw margin
*
* @return float
*
* @since 1.0.0
*/
public function winProbability(array $team1, array $team2, float $drawMargin = 0.0) : float
{
$sigmaSum = 0.0;
$mu1 = 0.0;
foreach ($team1 as $player) {
$mu1 += $player->mu;
$sigmaSum += $player->sigma * $player->sigma;
}
$mu2 = 0.0;
foreach ($team2 as $player) {
$mu2 += $player->mu;
$sigmaSum += $player->sigma * $player->sigma;
}
$deltaMu = $mu1 - $mu2;
return NormalDistribution::getCdf(
($deltaMu - $drawMargin) / \sqrt((\count($team1) + \count($team2)) * ($this->beta * $this->beta) + $sigmaSum),
0,
1
);
}
// Draw margin = epsilon
/**
* P_{draw} = 2\Phi\left(\dfrac{\epsilon}{\sqrt{n_1 + n_2} * \beta}\right) - 1
*/
public function drawProbability(float $drawMargin, int $n1, int $n2, float $beta)
{
return 2 * NormalDistribution::getCdf($drawMargin / (\sqrt($n1 + $n2) * $beta), 0.0, 1.0) - 1;
}
/**
* \epsilon = \Phi^{-1}\left(\dfrac{P_{draw} + 1}{2}\right) * \sqrt{n_1 + n_2} * \beta
*/
public function drawMargin(float $drawProbability, int $n1, int $n2, float $beta)
{
return NormalDistribution::getIcdf(($drawProbability + 1) / 2.0, 0.0, 1.0) * \sqrt($n1 + $n2) * $beta;
}
/**
* Mean additive truncated gaussion function "v" for wins
*
* @latex c = \sqrt{2 * \beta^2 + \sigma_{winner}^2 + \sigma_{loser}^2}
* @latex \mu_{winner} = \mu_{winner} + \dfrac{\sigma_{winner}^2}{c} * \nu \left(\dfrac{\mu_{winner} - \mu_{loser}}{c}, \dfrac{\epsilon}{c}\right)
* @latex \mu_{loser} = \mu_{loser} + \dfrac{\sigma_{loser}^2}{c} * \nu \left(\dfrac{\mu_{winner} - \mu_{loser}}{c}, \dfrac{\epsilon}{c}\right)
* @latex t = \dfrac{\mu_{winner} - \mu_{loser}}{c}
*
* @latex \nu = \dfrac{\mathcal{N}(t - \epsilon)}{\Phi(t - \epsilon)}
*
* @param float $t Difference winner and loser mu
* @param float $epsilon Draw margin
*
* @return float
*
* @since 1.0.0
*/
private function vWin(float $t, float $epsilon) : float
{
return NormalDistribution::getPdf($t - $epsilon, 0, 1.0) / NormalDistribution::getCdf($t - $epsilon, 0.0, 1.0);
}
/**
* Mean additive truncated gaussion function "v" for draws
*
* @latex c = \sqrt{2 * \beta^2 + \sigma_{winner}^2 + \sigma_{loser}^2}
* @latex \mu_{winner} = \mu_{winner} + \dfrac{\sigma_{winner}^2}{c} * \nu \left(\dfrac{\mu_{winner} - \mu_{loser}}{c}, \dfrac{\epsilon}{c}\right)
* @latex \mu_{loser} = \mu_{loser} + \dfrac{\sigma_{loser}^2}{c} * \nu \left(\dfrac{\mu_{winner} - \mu_{loser}}{c}, \dfrac{\epsilon}{c}\right)
* @latex t = \dfrac{\mu_{winner} - \mu_{loser}}{c}
* @latex \dfrac{\mathcal{N}(t - \epsilon)}{\Phi(t - \epsilon)}
*
* @latex \nu = \dfrac{\mathcal{N}(-\epsilon - t) - \mathcal{N}(\epsilon - t)}{\Phi(\epsilon - t) - \Phi(-\epsilon - t)}
*
* @param float $t Difference winner and loser mu
* @param float $epsilon Draw margin
*
* @return float
*
* @since 1.0.0
*/
private function vDraw(float $t, float $epsilon) : float
{
$tAbs = \abs($t);
$a = $epsilon - $tAbs;
$b = -$epsilon - $tAbs;
$aPdf = NormalDistribution::getPdf($a, 0.0, 1.0);
$bPdf = NormalDistribution::getPdf($b, 0.0, 1.0);
$numer = $bPdf - $aPdf;
$aCdf = NormalDistribution::getCdf($a, 0.0, 1.0);
$bCdf = NormalDistribution::getCdf($b, 0.0, 1.0);
$denom = $aCdf - $bCdf;
return $numer / $denom;
}
/**
* Variance multiplicative function "w" for draws
*
* @latex w = \nu * (\nu + t - \epsilon)
*
* @param float $t Difference winner and loser mu
* @param float $epsilon Draw margin
*
* @return float
*
* @since 1.0.0
*/
private function wWin(float $t, float $epsilon) : float
{
$v = $this->vWin($t, $epsilon);
return $v * ($v + $t - $epsilon);
}
/**
* Variance multiplicative function "w" for draws
*
* @latex w = \nu^2 + \dfrac{(\epsilon - t) * \mathcal{N}(\epsilon - t) + (\epsilon + t) * \mathcal{N}(\epsilon + t)}{\Phi(\epsilon - t) - \Phi(-\epsilon - t)}
*
* @param float $t Difference winner and loser mu
* @param float $epsilon Draw margin
*
* @return float
*
* @since 1.0.0
*/
private function wDraw(float $t, float $epsilon) : float
{
$tAbs = \abs($t);
$v = $this->vDraw($t, $epsilon);
return $v * $v
+ (($epsilon - $t) * NormalDistribution::getPdf($epsilon - $tAbs, 0.0, 1.0) + ($epsilon + $tAbs) * NormalDistribution::getPdf($epsilon + $tAbs, 0.0, 1.0))
/ (NormalDistribution::getCdf($epsilon - $tAbs, 0.0, 1.0) - NormalDistribution::getCdf(-$epsilon - $tAbs, 0.0, 1.0));
}
private function buildRatingLayer() : void
{
}
private function buildPerformanceLayer() : void
{
}
private function buildTeamPerformanceLayer() : void
{
}
private function buildTruncLayer() : void
{
}
private function factorGraphBuilders()
{
// Rating layer
// Performance layer
// Team Performance layer
// Trunc layer
return [
'rating_layer' => $ratingLayer,
'performance_layer' => $ratingLayer,
'team_performance_layer' => $ratingLayer,
'trunc_layer' => $ratingLayer,
];
}
public function rating() : void
{
// Start values
$mu = 25;
$sigma = $mu / 3;
$beta = $sigma / 2;
$tau = $sigma / 100;
$Pdraw = 0.1;
$alpha = 0.25;
// Partial update
$sigmaPartial = $sigmaOld * $sigmaNew / \sqrt($alpha * $sigmaOld * $sigmaOld - ($alpha - 1) * $sigmaNew * $sigmaNew);
$muPartial = $muOld * ($alpha - 1) * $sigmaNew * $sigmaNew - $muNew * $alpha * $sigmaOld * $sigmaOld
/ (($alpha - 1) * $sigmaNew * $sigmaNew - $alpha * $sigmaOld * $sigmaOld);
// New
$tau = $pi * $mu;
$P = NormalDistribution::getCdf(($s1 - $s2) / (\sqrt(2) * $beta));
$Delta = $alpha * $beta * \sqrt($pi) * (($y + 1) / 2 - $P);
$K = NormalDistribution::getCdf();
$pi = 1 / ($sigma * $sigma);
}
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Rating
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Rating;
/**
* Elo rating calculation using Elo rating
*
* @package phpOMS\Algorithm\Rating
* @license OMS License 2.0
* @link https://jingga.app
* @see https://en.wikipedia.org/wiki/Elo_rating_system
* @since 1.0.0
*/
final class TrueSkillFactoryGraph
{
}

86
Algorithm/Sort/BitonicSort.php Executable file
View File

@ -0,0 +1,86 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Sort;
/**
* BitonicSort class.
*
* @package phpOMS\Algorithm\Sort;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class BitonicSort implements SortInterface
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* {@inheritdoc}
*/
public static function sort(array $list, int $order = SortOrder::ASC) : array
{
$n = \count($list);
if ($n < 2) {
return $list;
}
$first = self::sort(\array_slice($list, 0, (int) ($n / 2)), SortOrder::ASC);
$second = self::sort(\array_slice($list, (int) ($n / 2)), SortOrder::DESC);
return self::merge(\array_merge($first, $second), $order);
}
/**
* Splitting, merging and sorting list
*
* @param array $list List to sort
* @param int $order Sort order
*
* @return array
*
* @since 1.0.0
*/
private static function merge(array $list, int $order) : array
{
$n = \count($list);
if ($n === 1) {
return $list;
}
$dist = $n / 2;
for ($i = 0; $i < $dist; ++$i) {
if ($list[$i]->compare($list[$i + $dist], $order)) {
$old = $list[$i];
$list[$i] = $list[$i + $dist];
$list[$i + $dist] = $old;
}
}
$first = self::merge(\array_slice($list, 0, (int) ($n / 2)), $order);
$second = self::merge(\array_slice($list, (int) ($n / 2)), $order);
return \array_merge($first, $second);
}
}

66
Algorithm/Sort/BubbleSort.php Executable file
View File

@ -0,0 +1,66 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Sort;
/**
* Bubblesort class.
*
* @package phpOMS\Algorithm\Sort;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class BubbleSort implements SortInterface
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* {@inheritdoc}
*/
public static function sort(array $list, int $order = SortOrder::ASC) : array
{
$n = \count($list);
if ($n < 2) {
return $list;
}
do {
$newN = 0;
for ($i = 1; $i < $n; ++$i) {
if ($list[$i - 1]->compare($list[$i], $order)) {
$old = $list[$i - 1];
$list[$i - 1] = $list[$i];
$list[$i] = $old;
$newN = $i;
}
}
$n = $newN;
} while ($n > 1);
return $list;
}
}

63
Algorithm/Sort/BucketSort.php Executable file
View File

@ -0,0 +1,63 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Sort;
/**
* Bucketsort class.
*
* @package phpOMS\Algorithm\Sort;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class BucketSort
{
/**
* Sort array
*
* @param array $list List of sortable elements
* @param int $bucketCount Buckets to divide the list into
* @param string $algo Algorithm to use for sort
* @param int $order Sort order
*
* @return array Sorted array
*
* @since 1.0.0
*/
public static function sort(array $list, int $bucketCount, string $algo = InsertionSort::class, int $order = SortOrder::ASC) : array
{
$buckets = [];
$M = $list[0]::max($list);
if ($bucketCount < 1) {
return [];
}
if (\count($list) < 2) {
return $list;
}
foreach ($list as $element) {
$buckets[(int) \floor(($bucketCount - 1) * $element->getValue() / $M)][] = $element;
}
$sorted = [];
foreach ($buckets as $bucket) {
$sorted[] = $algo::sort($bucket, SortOrder::ASC);
}
return $order === SortOrder::ASC ? \array_merge(...$sorted) : \array_reverse(\array_merge(...$sorted), false);
}
}

View File

@ -0,0 +1,80 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Sort;
/**
* CocktailShakerSort class.
*
* @package phpOMS\Algorithm\Sort;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class CocktailShakerSort implements SortInterface
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* {@inheritdoc}
*/
public static function sort(array $list, int $order = SortOrder::ASC) : array
{
$start = 0;
$end = \count($list) - 1;
if ($end < 1) {
return $list;
}
while ($start <= $end) {
$newStart = $end;
$newEnd = $start;
for ($i = $start; $i < $end; ++$i) {
if ($list[$i]->compare($list[$i + 1], $order)) {
$old = $list[$i];
$list[$i] = $list[$i + 1];
$list[$i + 1] = $old;
$newEnd = $i;
}
}
$end = $newEnd - 1;
for ($i = $end; $i >= $start; --$i) {
if ($list[$i]->compare($list[$i + 1], $order)) {
$old = $list[$i];
$list[$i] = $list[$i + 1];
$list[$i + 1] = $old;
$newStart = $i;
}
}
$start = $newStart + 1;
}
return $list;
}
}

75
Algorithm/Sort/CombSort.php Executable file
View File

@ -0,0 +1,75 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Sort;
/**
* CombSort class.
*
* @package phpOMS\Algorithm\Sort;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class CombSort implements SortInterface
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* {@inheritdoc}
*/
public static function sort(array $list, int $order = SortOrder::ASC) : array
{
$sorted = false;
$n = \count($list);
$gap = $n;
$shrink = 1.3;
if ($n < 2) {
return $list;
}
while (!$sorted) {
$gap = (int) \floor($gap / $shrink);
if ($gap < 2) {
$gap = 1;
$sorted = true;
}
$i = 0;
while ($i + $gap < $n) {
if ($list[$i]->compare($list[$i + $gap], $order)) {
$old = $list[$i];
$list[$i] = $list[$i + 1];
$list[$i + 1] = $old;
$sorted = false;
}
++$i;
}
}
return $list;
}
}

96
Algorithm/Sort/CycleSort.php Executable file
View File

@ -0,0 +1,96 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Sort;
/**
* CycleSort class.
*
* @package phpOMS\Algorithm\Sort;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class CycleSort implements SortInterface
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* {@inheritdoc}
*/
public static function sort(array $list, int $order = SortOrder::ASC) : array
{
$n = \count($list);
if ($n < 2) {
return $list;
}
for ($start = 0; $start < $n - 1; ++$start) {
$item = $list[$start];
$pos = $start;
$length0 = \count($list);
for ($i = $start + 1; $i < $length0; ++$i) {
if (!$list[$i]->compare($item, $order)) {
++$pos;
}
}
if ($pos === $start) {
continue;
}
while ($item->equals($list[$pos])) {
++$pos;
}
if ($pos !== $start) {
$old = $list[$pos];
$list[$pos] = $item;
$item = $old;
}
while ($pos !== $start) {
$pos = $start;
for ($i = $start + 1; $i < $n; ++$i) {
if (!$list[$i]->compare($item, $order)) {
++$pos;
}
}
while (isset($list[$pos]) && $item->equals($list[$pos])) {
++$pos;
}
if (isset($list[$pos])) {
$old = $list[$pos];
$list[$pos] = $item;
$item = $old;
}
}
}
return $list;
}
}

62
Algorithm/Sort/GnomeSort.php Executable file
View File

@ -0,0 +1,62 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Sort;
/**
* GnomeSort class.
*
* @package phpOMS\Algorithm\Sort;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class GnomeSort implements SortInterface
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* {@inheritdoc}
*/
public static function sort(array $list, int $order = SortOrder::ASC) : array
{
$n = \count($list);
if ($n < 2) {
return $list;
}
for ($i = 1; $i < $n; ++$i) {
$j = $i;
while ($j > 0 && $list[$j - 1]->compare($list[$j], $order)) {
$old = $list[$j - 1];
$list[$j - 1] = $list[$j];
$list[$j] = $old;
--$j;
}
}
return $list;
}
}

98
Algorithm/Sort/HeapSort.php Executable file
View File

@ -0,0 +1,98 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Sort;
/**
* HeapSort class.
*
* @package phpOMS\Algorithm\Sort;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class HeapSort implements SortInterface
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* {@inheritdoc}
*/
public static function sort(array $list, int $order = SortOrder::ASC) : array
{
$n = \count($list);
if ($n < 2) {
return $list;
}
$copy = $list;
for ($p = (int) ($n / 2 - 1); $p >= 0; --$p) {
self::heapify($copy, $n, $p, $order);
}
for ($i = $n - 1; $i > 0; --$i) {
$temp = $copy[$i];
$copy[$i] = $copy[0];
$copy[0] = $temp;
--$n;
self::heapify($copy, $n, 0, $order);
}
return $copy;
}
/**
* Convert into heap data structure
*
* @param array $list Data to sort
* @param int $size Heap size
* @param int $index Index element
* @param int $order Sort order
*
* @return void
*
* @since 1.0.0
*/
private static function heapify(array &$list, int $size, int $index, int $order) : void
{
$left = ($index + 1) * 2 - 1;
$right = ($index + 1) * 2;
$pivot = 0;
$pivot = $left < $size && $list[$left]->compare($list[$index], $order) ? $left : $index;
if ($right < $size && $list[$right]->compare($list[$pivot], $order)) {
$pivot = $right;
}
if ($pivot !== $index) {
$temp = $list[$index];
$list[$index] = $list[$pivot];
$list[$pivot] = $temp;
self::heapify($list, $size, $pivot, $order);
}
}
}

View File

@ -0,0 +1,62 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Sort;
/**
* InsertionSort class.
*
* @package phpOMS\Algorithm\Sort;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class InsertionSort implements SortInterface
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* {@inheritdoc}
*/
public static function sort(array $list, int $order = SortOrder::ASC) : array
{
$n = \count($list);
if ($n < 2) {
return $list;
}
for ($i = 1; $i < $n; ++$i) {
$pivot = $list[$i];
$j = $i - 1;
while ($j >= 0 && $list[$j]->compare($pivot, $order)) {
$list[$j + 1] = $list[$j];
--$j;
}
$list[$j + 1] = $pivot;
}
return $list;
}
}

88
Algorithm/Sort/IntroSort.php Executable file
View File

@ -0,0 +1,88 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Sort;
/**
* IntroSort class.
*
* @package phpOMS\Algorithm\Sort;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class IntroSort implements SortInterface
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* {@inheritdoc}
*/
public static function sort(array $list, int $order = SortOrder::ASC) : array
{
$clone = $list;
$size = self::partition($clone, 0, \count($list) - 1, $order);
if ($size < 16) {
return InsertionSort::sort($clone, $order);
}
if ($size > \log(\count($list)) * 2) {
return HeapSort::sort($clone, $order);
}
return QuickSort::sort($clone);
}
/**
* Partition list and return the size
*
* @param array $list List reference
* @param int $lo Low or left side
* @param int $hi High or right side
* @param int $order Order type
*
* @return int
*
* @since 1.0.0
*/
private static function partition(array &$list, int $lo, int $hi, int $order) : int
{
$pivot = $list[$hi];
$i = $lo;
for ($j = $lo; $j < $hi; ++$j) {
if ($list[$j]->compare($pivot, $order)) {
$temp = $list[$j];
$list[$j] = $list[$i];
$list[$i] = $temp;
++$i;
}
}
$list[$hi] = $list[$i];
$list[$i] = $pivot;
return $i;
}
}

137
Algorithm/Sort/MergeSort.php Executable file
View File

@ -0,0 +1,137 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Sort;
/**
* MergeSort class.
*
* @package phpOMS\Algorithm\Sort;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class MergeSort implements SortInterface
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* {@inheritdoc}
*/
public static function sort(array $list, int $order = SortOrder::ASC) : array
{
$n = \count($list);
if ($n < 2) {
return $list;
}
$clone = $list;
self::sortHalve($clone, 0, $n - 1, $order);
return $clone;
}
/**
* Recursive sorting of halve of the list and then merging it
*
* @param array $list Data to sort
* @param int $lo Start of the list to sort
* @param int $hi End of the list to sort
* @param int $order Sort order
*
* @return void
*
* @since 1.0.0
*/
private static function sortHalve(array &$list, int $lo, int $hi, int $order) : void
{
if ($lo >= $hi) {
return;
}
$mi = (int) ($lo + ($hi - $lo) / 2);
self::sortHalve($list, $lo, $mi, $order);
self::sortHalve($list, $mi + 1, $hi, $order);
self::merge($list, $lo, $mi, $hi, $order);
}
/**
* Merge and sort sub list
*
* @param array $list Data to sort
* @param int $lo Start of the list to sort
* @param int $mi Middle point of the list to sort
* @param int $hi End of the list to sort
* @param int $order Sort order
*
* @return void
*
* @since 1.0.0
*/
private static function merge(array &$list, int $lo, int $mi, int $hi, int $order) : void
{
$n1 = $mi - $lo + 1;
$n2 = $hi - $mi;
$loList = [];
$hiList = [];
for ($i = 0; $i < $n1; ++$i) {
$loList[$i] = $list[$lo + $i];
}
for ($i = 0; $i < $n2; ++$i) {
$hiList[$i] = $list[$mi + 1 + $i];
}
$i = 0;
$j = 0;
$k = $lo;
while ($i < $n1 && $j < $n2) {
if (!$loList[$i]->compare($hiList[$j], $order)) {
$list[$k] = $loList[$i];
++$i;
} else {
$list[$k] = $hiList[$j];
++$j;
}
++$k;
}
while ($i < $n1) {
$list[$k] = $loList[$i];
++$i;
++$k;
}
while ($j < $n2) {
$list[$k] = $hiList[$j];
++$j;
++$k;
}
}
}

75
Algorithm/Sort/OddEvenSort.php Executable file
View File

@ -0,0 +1,75 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package phpOMS\Algorithm\Sort;
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace phpOMS\Algorithm\Sort;
/**
* OddEvenSort class.
*
* @package phpOMS\Algorithm\Sort;
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class OddEvenSort implements SortInterface
{
/**
* Constructor
*
* @since 1.0.0
* @codeCoverageIgnore
*/
private function __construct()
{
}
/**
* {@inheritdoc}
*/
public static function sort(array $list, int $order = SortOrder::ASC) : array
{
$sorted = false;
$n = \count($list);
if ($n < 2) {
return $list;
}
while (!$sorted) {
$sorted = true;
for ($i = 1; $i < $n - 1; $i += 2) {
if ($list[$i]->compare($list[$i + 1], $order)) {
$old = $list[$i];
$list[$i] = $list[$i + 1];
$list[$i + 1] = $old;
$sorted = false;
}
}
for ($i = 0; $i < $n - 1; $i += 2) {
if ($list[$i]->compare($list[$i + 1], $order)) {
$old = $list[$i];
$list[$i] = $list[$i + 1];
$list[$i + 1] = $old;
$sorted = false;
}
}
}
return $list;
}
}

Some files were not shown because too many files have changed in this diff Show More