kabk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +20 -0
  3. data/Gemfile +6 -0
  4. data/Gemfile.lock +105 -0
  5. data/Kabk_logo.svg +33 -0
  6. data/LICENSE +21 -0
  7. data/README.md +112 -0
  8. data/doc/Kabk/Adapters/Base.html +989 -0
  9. data/doc/Kabk/Adapters/SequelAdapter.html +1071 -0
  10. data/doc/Kabk/Adapters.html +120 -0
  11. data/doc/Kabk/ApiError.html +511 -0
  12. data/doc/Kabk/Auth/JwtStrategy.html +551 -0
  13. data/doc/Kabk/Auth.html +118 -0
  14. data/doc/Kabk/Concurrency.html +297 -0
  15. data/doc/Kabk/ConcurrencyConflictError.html +234 -0
  16. data/doc/Kabk/Error.html +140 -0
  17. data/doc/Kabk/ExportHandler.html +381 -0
  18. data/doc/Kabk/Field.html +2160 -0
  19. data/doc/Kabk/ForbiddenError.html +234 -0
  20. data/doc/Kabk/InvalidFieldError.html +145 -0
  21. data/doc/Kabk/InvalidOldPasswordError.html +234 -0
  22. data/doc/Kabk/NotFoundError.html +234 -0
  23. data/doc/Kabk/QueryBuilder.html +701 -0
  24. data/doc/Kabk/Registry.html +608 -0
  25. data/doc/Kabk/RelationHydrator.html +480 -0
  26. data/doc/Kabk/Resource.html +1986 -0
  27. data/doc/Kabk/ResourceBuilder.html +1002 -0
  28. data/doc/Kabk/RestEngine.html +887 -0
  29. data/doc/Kabk/SchemaRenderer.html +318 -0
  30. data/doc/Kabk/UnauthorizedError.html +234 -0
  31. data/doc/Kabk/UploadHandler.html +308 -0
  32. data/doc/Kabk/ValidationError.html +234 -0
  33. data/doc/Kabk/Validator.html +802 -0
  34. data/doc/Kabk.html +330 -0
  35. data/doc/_index.html +369 -0
  36. data/doc/class_list.html +54 -0
  37. data/doc/css/common.css +1 -0
  38. data/doc/css/full_list.css +206 -0
  39. data/doc/css/style.css +1089 -0
  40. data/doc/file.README.html +162 -0
  41. data/doc/file_list.html +59 -0
  42. data/doc/frames.html +22 -0
  43. data/doc/index.html +162 -0
  44. data/doc/js/app.js +801 -0
  45. data/doc/js/full_list.js +334 -0
  46. data/doc/js/jquery.js +4 -0
  47. data/doc/method_list.html +982 -0
  48. data/doc/top-level-namespace.html +112 -0
  49. data/docs/API_REFERENCE.md +255 -0
  50. data/lib/kabk/adapters/base.rb +53 -0
  51. data/lib/kabk/adapters/sequel_adapter.rb +138 -0
  52. data/lib/kabk/concurrency.rb +30 -0
  53. data/lib/kabk/errors.rb +68 -0
  54. data/lib/kabk/field.rb +97 -0
  55. data/lib/kabk/query_builder.rb +103 -0
  56. data/lib/kabk/registry.rb +41 -0
  57. data/lib/kabk/relation_hydrator.rb +107 -0
  58. data/lib/kabk/resource.rb +88 -0
  59. data/lib/kabk/resource_builder.rb +95 -0
  60. data/lib/kabk/rest_engine.rb +120 -0
  61. data/lib/kabk/schema_renderer.rb +69 -0
  62. data/lib/kabk/upload_handler.rb +24 -0
  63. data/lib/kabk/validator.rb +121 -0
  64. data/lib/kabk/version.rb +6 -0
  65. data/lib/kabk.rb +50 -0
  66. metadata +178 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: af2b44890e6b0d0a9044457ef3af1288ca81f730a6df68b0d4bca8995412c3d2
4
+ data.tar.gz: 37d8aabe0c2eeee5a8678852eab539fff726a2cb19dcf2ecce12b3589d38824e
5
+ SHA512:
6
+ metadata.gz: e8b41f12e6ae3607a90c5ce4535161c96cbd94850bf2b5aaa669445d5a6ecb9abf8f6cd1df1657264dc79bce818eab0036a80753a1193208944c519dc9226359
7
+ data.tar.gz: de616125d211efe67168192532898280da5f9c6ae92117e2954f0b0ece6337a83a43b002ebbe528a0967a03d82c8bb297b48159988ad74247be808074e2fe0a6
data/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2026-08-15
9
+
10
+ ### Added
11
+ - Initial stable release of the `kabk` gem.
12
+ - Framework-agnostic core engine for Schema-Driven Dynamic Admin Specification (Protocol v1.6.0).
13
+ - Resource registration DSL with declarative field definitions, relationships, and lifecycle hooks (`before_create`, `after_create`, `before_update`, `after_update`, `before_delete`, `after_delete`).
14
+ - Generic CRUD REST Engine (`Kabk::RestEngine`) with support for pagination, sorting, filtering (exact match, IN lists, range queries), and search.
15
+ - Pluggable ORM Adapter architecture with built-in `Kabk::Adapters::SequelAdapter`.
16
+ - Robust server-side validation and parameter sanitization (`Kabk::Validator`).
17
+ - Optimistic Concurrency Control (OCC) conflict detection (`Kabk::Concurrency`).
18
+ - Relational data hydration (`Kabk::RelationHydrator`) to eliminate N+1 queries.
19
+ - JSON Schema manifest generation (`Kabk::SchemaRenderer`) for dynamic UI configuration.
20
+ - Comprehensive YARD documentation and RSpec test suite.
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "sqlite3"
6
+ gem "rspec"
data/Gemfile.lock ADDED
@@ -0,0 +1,105 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ kabk (1.0.0)
5
+ concurrent-ruby (~> 1.1)
6
+ sequel (~> 5.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ ast (2.4.3)
12
+ bigdecimal (4.0.1)
13
+ concurrent-ruby (1.3.8)
14
+ diff-lcs (1.6.2)
15
+ json (2.21.2)
16
+ language_server-protocol (3.17.0.6)
17
+ lint_roller (1.1.0)
18
+ parallel (2.1.0)
19
+ parser (3.3.12.0)
20
+ ast (~> 2.4.1)
21
+ racc
22
+ prism (1.9.0)
23
+ racc (1.8.1)
24
+ rainbow (3.1.1)
25
+ regexp_parser (2.12.0)
26
+ rspec (3.13.2)
27
+ rspec-core (~> 3.13.0)
28
+ rspec-expectations (~> 3.13.0)
29
+ rspec-mocks (~> 3.13.0)
30
+ rspec-core (3.13.6)
31
+ rspec-support (~> 3.13.0)
32
+ rspec-expectations (3.13.5)
33
+ diff-lcs (>= 1.2.0, < 2.0)
34
+ rspec-support (~> 3.13.0)
35
+ rspec-mocks (3.13.8)
36
+ diff-lcs (>= 1.2.0, < 2.0)
37
+ rspec-support (~> 3.13.0)
38
+ rspec-support (3.13.7)
39
+ rubocop (1.89.0)
40
+ json (~> 2.3)
41
+ language_server-protocol (~> 3.17.0.2)
42
+ lint_roller (~> 1.1.0)
43
+ parallel (>= 1.10)
44
+ parser (>= 3.3.0.2)
45
+ rainbow (>= 2.2.2, < 4.0)
46
+ regexp_parser (>= 2.9.3, < 3.0)
47
+ rubocop-ast (>= 1.49.0, < 2.0)
48
+ ruby-progressbar (~> 1.7)
49
+ unicode-display_width (>= 2.4.0, < 4.0)
50
+ rubocop-ast (1.50.0)
51
+ parser (>= 3.3.7.2)
52
+ prism (~> 1.7)
53
+ ruby-progressbar (1.13.0)
54
+ sequel (5.107.0)
55
+ bigdecimal
56
+ sqlite3 (2.9.5-x64-mingw-ucrt)
57
+ unicode-display_width (3.2.0)
58
+ unicode-emoji (~> 4.1)
59
+ unicode-emoji (4.2.0)
60
+ webrick (1.9.2)
61
+ yard (0.9.45)
62
+
63
+ PLATFORMS
64
+ x64-mingw-ucrt
65
+
66
+ DEPENDENCIES
67
+ kabk!
68
+ rspec
69
+ rubocop (~> 1.21)
70
+ sqlite3
71
+ webrick
72
+ yard (~> 0.9)
73
+
74
+ CHECKSUMS
75
+ ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
76
+ bigdecimal (4.0.1) sha256=8b07d3d065a9f921c80ceaea7c9d4ae596697295b584c296fe599dd0ad01c4a7
77
+ concurrent-ruby (1.3.8) sha256=b2f1be836e968ccc78ccfce277ea79c72a88633f22306782c16ff23fb415d1e1
78
+ diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962
79
+ json (2.21.2) sha256=1f1d3b7cf2b3ba1a69beca0bb6db13d5438b80bff3cd54cdaaa620b9b07c1c6a
80
+ kabk (1.0.0)
81
+ language_server-protocol (3.17.0.6) sha256=5ef2c0c138f8267e1bc631d3328347d354f96724b0af22f2c79516120443b7f0
82
+ lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
83
+ parallel (2.1.0) sha256=b35258865c2e31134c5ecb708beaaf6772adf9d5efae28e93e99260877b09356
84
+ parser (3.3.12.0) sha256=21a6d7f755d5a24dfbdc6e6b772e4e879a52e7631a88bc5a3a134606052c9828
85
+ prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
86
+ racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
87
+ rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
88
+ regexp_parser (2.12.0) sha256=35a916a1d63190ab5c9009457136ae5f3c0c7512d60291d0d1378ba18ce08ebb
89
+ rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587
90
+ rspec-core (3.13.6) sha256=a8823c6411667b60a8bca135364351dda34cd55e44ff94c4be4633b37d828b2d
91
+ rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836
92
+ rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47
93
+ rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
94
+ rubocop (1.89.0) sha256=4dee8e3ee9c45e474834efd9e8d6fd031e8331c8dacdff0de4ad65ae0a6faae7
95
+ rubocop-ast (1.50.0) sha256=b9ca88300da0803ee222ad20cdb30494c0a784eed06fdc35d254b06d662788db
96
+ ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
97
+ sequel (5.107.0) sha256=019629313205295b007f6df2c5eab19ddc40710d549fd445ac300f2853a370db
98
+ sqlite3 (2.9.5-x64-mingw-ucrt) sha256=b00d5697994ee8589b6096694a2130aa5567db64373baca55ea98c9bf958f46a
99
+ unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
100
+ unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
101
+ webrick (1.9.2) sha256=beb4a15fc474defed24a3bda4ffd88a490d517c9e4e6118c3edce59e45864131
102
+ yard (0.9.45) sha256=52e211493f7cb8a3ebf7e104a25a1e73937a3103092545d34cb88fafebb3dc51
103
+
104
+ BUNDLED WITH
105
+ 4.0.16
data/Kabk_logo.svg ADDED
@@ -0,0 +1,33 @@
1
+ <svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 395 395.6" width="700" height="701.7721518987341">
2
+ <defs>
3
+ <linearGradient id="g1" x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(263.757,275.126,-433.936,452.641,65,4)">
4
+ <stop offset="0" stop-color="#e0334f"/>
5
+ <stop offset=".45" stop-color="#c41e3a"/>
6
+ <stop offset="1" stop-color="#7a1128"/>
7
+ </linearGradient>
8
+ <linearGradient id="g2" x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(9.217,8.903,-9.218,8.904,280.9,21.68)">
9
+ <stop offset="0" stop-color="#e0334f"/>
10
+ <stop offset=".45" stop-color="#c41e3a"/>
11
+ <stop offset="1" stop-color="#7a1128"/>
12
+ </linearGradient>
13
+ <linearGradient id="g3" x2="1" gradientUnits="userSpaceOnUse" gradientTransform="matrix(331.999,81.601,-330.561,81.247,36.979,287.999)">
14
+ <stop offset="0" stop-color="#e0334f"/>
15
+ <stop offset=".45" stop-color="#c41e3a"/>
16
+ <stop offset="1" stop-color="#7a1128"/>
17
+ </linearGradient>
18
+ </defs>
19
+ <style>
20
+ .s0 { fill: url(#g1) }
21
+ .s1 { fill: url(#g2) }
22
+ .s2 { fill: url(#g3) }
23
+ </style>
24
+ <g>
25
+ <g>
26
+ <path class="s0" d="m278.28 4.04c-0.18 0.04-1.11 0.19-2.08 0.32-0.96 0.13-2.29 0.4-2.94 0.57q-3.27 0.88-4.31 1.33c-0.37 0.16-0.78 0.29-0.91 0.29-0.55 0-5.9 2.77-7.56 3.91-4.33 2.95-8.96 7.36-11.03 10.5-0.18 0.27-0.59 0.88-0.94 1.34-2.08 2.92-4.7 8.05-6.16 11.99-0.15 0.41-0.41 1.15-0.61 1.63-0.68 1.86-1.92 6.12-2.49 8.52-0.68 2.99-0.96 4.2-1.14 4.92-0.08 0.41-0.28 1.11-0.41 1.53-0.15 0.41-0.46 1.35-0.7 2.07-0.22 0.72-0.63 1.86-0.87 2.51-0.27 0.66-0.55 1.47-0.66 1.77-0.28 0.94-0.85 1.68-1.42 1.81-0.26 0.07-0.96 0.64-1.51 1.25l-1 1.11v1.09c0 1.45-0.37 2.06-2.12 3.61-3.65 3.21-8.93 5.98-15.68 8.25-0.83 0.29-2.08 0.75-2.73 0.99-0.66 0.26-1.88 0.7-2.73 0.98-0.83 0.28-2.08 0.72-2.73 0.98-2.64 1.01-2.97 1.14-3.39 1.23-0.24 0.06-0.63 0.21-0.87 0.3-0.24 0.11-0.98 0.42-1.64 0.66-1.29 0.5-3.97 1.59-5.24 2.12-1.01 0.41-1.33 0.54-3.34 1.46-0.92 0.44-1.75 0.79-1.82 0.79-0.45 0-10.59 5.32-14.28 7.49-5.66 3.34-14.55 9.54-18.87 13.12-8.26 6.91-14.18 12.74-19.81 19.57-0.66 0.79-1.4 1.66-1.66 1.97-1.84 2.07-7.54 9.81-9.59 12.99-1.31 2.01-5.55 9.07-6.38 10.6-0.35 0.65-0.87 1.59-1.13 2.07-0.59 1.03-2.67 5.18-3.78 7.54-1.29 2.73-1.75 3.82-3.84 8.84-0.11 0.24-0.51 1.16-0.88 2.06-0.37 0.87-0.68 1.7-0.68 1.81 0 0.13-0.13 0.52-0.3 0.89-0.42 0.97-1.09 2.76-1.99 5.18-0.96 2.58-2.64 6.2-3.93 8.41-0.41 0.72-0.85 1.55-0.98 1.83-0.13 0.29-0.51 0.92-0.85 1.42-0.35 0.48-0.99 1.45-1.4 2.1-0.44 0.66-1.18 1.79-1.66 2.51-0.5 0.72-1.01 1.51-1.16 1.73-0.46 0.68-2.82 3.93-4.22 5.83-0.72 0.96-1.52 2.07-1.81 2.45-0.26 0.39-0.68 0.94-0.92 1.24-0.96 1.25-4.21 5.4-4.58 5.81-0.22 0.26-0.99 1.25-1.73 2.18-0.74 0.97-1.9 2.43-2.6 3.3-0.67 0.85-1.72 2.19-2.33 2.95-0.59 0.77-1.62 2.01-2.25 2.8-1.25 1.5-1.4 1.66-2.78 3.38-0.46 0.61-0.91 1.14-0.98 1.2-0.52 0.44-4.85 6.49-6.22 8.74l-0.62 0.96-0.02 1.55-0.02 1.53 0.44 0.59c1.48 1.97 5.02 1.44 9.39-1.35 0.37-0.24 0.81-0.51 0.98-0.59 0.44-0.22 3.15-2.08 4.28-2.93l0.9-0.66 1.02 0.27 1.03 0.26 2.34-0.11 2.33-0.11 0.88-0.39c2.14-0.94 3.86-1.82 5.79-2.95 1.13-0.68 2.22-1.29 2.4-1.38 0.17-0.08 0.63-0.35 0.98-0.59 0.37-0.24 0.81-0.5 0.98-0.59 0.18-0.06 0.73-0.39 1.21-0.7 0.48-0.3 1.04-0.65 1.24-0.78 1.94-1.14 6.77-4.17 8.65-5.46 8.45-5.7 8.37-5.66 11.84-6.23 0.92-0.15 2.38-0.5 4.8-1.11 0.55-0.13 1.58-0.39 2.3-0.57 0.72-0.17 1.85-0.46 2.51-0.65 0.65-0.18 1.7-0.46 2.29-0.62q3.41-0.91 4.37-1.24c0.37-0.13 0.92-0.28 1.24-0.33l0.59-0.11 0.83 0.64c1.75 1.35 7.41 4.32 11.32 5.94 0.96 0.39 2.05 0.85 2.4 1 0.37 0.15 1.01 0.35 1.42 0.44 0.42 0.09 0.87 0.24 0.98 0.33 0.22 0.17 3.45 1.22 5.57 1.81 1.12 0.33 1.84 0.48 5.9 1.35 0.79 0.18 2.4 0.48 3.6 0.68 1.2 0.22 2.32 0.48 2.47 0.59l0.26 0.2v1.2c0 2.36 1.05 4.89 3.83 9.13 0.39 0.59 0.76 1.37 0.83 1.74 0.04 0.35 0.19 0.94 0.32 1.32 0.13 0.34 0.4 1.24 0.61 1.96 0.2 0.72 0.51 1.79 0.68 2.4 0.42 1.42 0.81 2.76 1.27 4.37 0.2 0.72 0.46 1.6 0.59 1.97 0.11 0.35 0.3 1 0.39 1.42 0.11 0.41 0.39 1.44 0.63 2.29 0.27 0.83 0.57 1.92 0.68 2.4 0.11 0.48 0.35 1.47 0.53 2.19 0.17 0.72 0.41 1.59 0.52 1.96 0.11 0.35 0.37 1.2 0.57 1.86 0.17 0.65 0.5 1.7 0.68 2.34l0.34 1.13-0.3 0.61c-0.59 1.14-2.25 2.21-3.87 2.49-2.42 0.44-3.93 0.83-5.13 1.4l-1.31 0.63-1.22 1.25-1.25 1.24-0.59 1.25c-0.61 1.31-1.11 2.93-1.33 4.3l-0.13 0.79 0.39 0.19 0.42 0.22 6.11-0.17 6.12-0.15 1.64-0.35c0.89-0.18 2.22-0.48 2.94-0.68 0.73-0.22 1.62-0.42 2.01-0.48l0.7-0.11 1.82 0.55c1 0.3 2.55 0.69 3.45 0.87 0.89 0.2 2.38 0.5 3.27 0.68l1.64 0.35h16.12 16.12l0.46-0.24 0.43-0.24-0.15-1.29-0.15-1.29 0.33-0.13c0.17-0.07 0.89 0.04 1.59 0.22l1.29 0.32 15.29 0.02c8.41 0.03 15.42 0.03 15.57 0.03l0.26-0.03v-1.52-1.51l-0.37-0.83c-0.63-1.38-2.18-3.28-3.52-4.26-1.55-1.18-3.34-2.05-5.28-2.58l-0.98-0.26-7.65-0.17c-15.05-0.33-16.9-1.07-21.97-8.85-1.99-3.04-2.82-4.39-2.82-4.54 0-0.07-0.28-0.57-0.65-1.09-0.35-0.55-0.66-1.05-0.66-1.12 0-0.06-0.39-0.79-0.89-1.57-0.48-0.81-0.99-1.68-1.1-1.92-0.1-0.27-0.39-0.77-0.63-1.12-0.24-0.37-0.52-0.85-0.65-1.09-0.11-0.24-0.55-1.03-0.97-1.75-0.41-0.72-1.02-1.81-1.33-2.4-0.33-0.61-0.89-1.68-1.31-2.4-1.18-2.1-1.64-3.06-1.64-3.41 0.03-0.44 2.19-4.69 3.3-6.42 0.22-0.37 0.48-0.79 0.57-0.96 0.68-1.42 3.14-4.44 5.96-7.23 3.85-3.87 6.14-5.42 10.81-7.32 2.21-0.91 3-1.29 7.65-3.49 1.81-0.88 3.43-1.64 3.6-1.73 0.33-0.13 0.57-0.28 3.63-2.12 0.98-0.59 1.85-1.07 1.92-1.07 0.07 0 0.55-0.28 1.05-0.65 0.48-0.37 0.96-0.66 1.05-0.66 0.19 0 4.82-3.08 5.92-3.95 0.43-0.35 0.87-0.63 0.96-0.63 0.13 0 1.81-1.25 2.07-1.53 0.07-0.07 1.01-0.81 2.08-1.64 7.23-5.55 16.6-15.59 21.55-23.13 1.58-2.4 4-6.42 4.9-8.1 3.62-6.93 5.06-10.22 7.09-16.49 0.62-1.86 1.25-3.74 1.4-4.15 0.48-1.31 1.38-4.9 1.64-6.51 0.11-0.64 0.28-1.62 0.41-2.19 0.79-3.53 1.27-7.27 1.69-13.25l0.32-4.81-0.1-3.38c-0.25-6.32-0.66-11.21-1.36-15.51-0.3-1.92-0.48-2.78-1.16-5.46-0.15-0.55-0.46-2.51-0.7-4.37-0.45-3.49-0.96-5.31-1.81-6.44-0.65-0.92-1.13-1.97-1.55-3.5-0.22-0.72-0.61-2.01-0.92-2.84-0.28-0.85-0.59-1.72-0.65-1.96-0.05-0.24-0.2-0.64-0.31-0.88-1.15-2.62-2.36-8.56-2.09-10.28 0.06-0.48 0.21-1.44 0.35-2.19 0.21-1.53 1.02-3.34 2.27-5.22l0.89-1.31 5.03-5 5.04-5.02 2.29-0.29c1.27-0.15 3.28-0.37 4.48-0.48 1.2-0.13 2.78-0.3 3.5-0.43 0.72-0.14 2.14-0.24 3.14-0.24h1.84l1.07 0.65c4.95 3.06 2.92-7.03-2.56-12.69-1.11-1.16-6.05-5-6.42-5-0.11 0-0.79-0.31-1.51-0.66-0.74-0.37-1.44-0.65-1.55-0.65-0.13 0-0.68-0.22-1.22-0.48l-0.98-0.48-0.46-1.01c-0.92-2.01-1.2-2.53-2.14-4.15-1.77-2.99-3.15-4.5-6.29-6.77-2.43-1.79-7.47-4.26-9.57-4.69-0.35-0.07-1.2-0.27-1.86-0.44-0.65-0.15-1.74-0.42-2.4-0.57l-1.2-0.26-4.59-0.07c-2.51-0.02-4.74-0.02-4.91 0.03zm9.5 4.43c0.85 0.11 1.88 0.31 2.29 0.44 0.42 0.13 1.51 0.46 2.41 0.72 0.89 0.28 1.79 0.57 1.96 0.65 1.55 0.72 3.71 1.84 4.26 2.17 0.37 0.24 0.81 0.5 0.98 0.58 1.4 0.62 5.44 4.7 6.29 6.34 0.53 1 0.7 1.37 0.64 1.37-0.02 0-0.83-0.24-1.77-0.54-2.01-0.63-2.78-0.68-4.72-0.2l-1.42 0.35h-2.45-2.42l-0.5-0.28c-0.29-0.16-0.81-0.35-1.18-0.44-0.35-0.09-1.2-0.37-1.86-0.63-0.65-0.26-1.83-0.61-2.62-0.77l-1.42-0.28-1.86 0.22-1.85 0.19-1.53 0.77c-0.83 0.39-1.99 1.11-2.56 1.55-2.9 2.36-3.73 2.95-4.78 3.49-0.63 0.31-1.46 0.64-1.81 0.75-0.81 0.19-1.95 0.56-2.93 0.98-0.39 0.17-0.89 0.3-1.13 0.3-0.22 0-0.68 0.14-1.03 0.31-0.33 0.18-1.01 0.48-1.49 0.68-1.5 0.61-3.6 1.72-3.6 1.88 0 0.08-0.22 0.24-0.48 0.32-0.63 0.2-2.77 2.25-3.87 3.69-2.49 3.26-3.75 6.64-4.17 11.08l-0.19 2.14 0.19 2.12c0.66 7.25 5 14.35 12.45 20.35 2.86 2.3 7.91 6.69 9.59 8.32 1.2 1.18 3.52 3.91 4.8 5.68l1.36 1.86 1.55 3.17c3.19 6.53 5.68 10.18 7.69 11.25l1.02 0.54h0.99 0.96l0.85-0.52c1.59-1.01 3.04-3.54 4.28-7.49 0.44-1.38 0.7-1.6 0.98-0.83l0.22 0.59-0.19 1.22c-0.49 2.84-1.08 5-1.69 6.2-0.17 0.31-0.3 0.7-0.3 0.83 0 0.53-2.91 6.27-4.09 8.04-2.73 4.17-7.42 9-8.73 9-0.09 0-0.33 0.17-0.57 0.37l-0.42 0.39-1.35-0.02h-1.35l-0.64-0.35c-0.37-0.17-1-0.48-1.42-0.65-1.68-0.75-4.72-2.28-5.39-2.73-0.42-0.29-1.05-0.66-1.42-0.86-6.14-3.16-23.02-19.63-27.54-26.86-0.31-0.48-0.68-1.03-0.86-1.2-0.17-0.18-0.54-0.7-0.83-1.18-0.28-0.48-0.61-0.98-0.72-1.09-1.63-1.99-7.2-12.78-7.66-14.9l-0.16-0.7 0.75-0.83c1.24-1.4 4.08-6.22 4.08-6.97 0-0.06 0.13-0.43 0.31-0.8 0.59-1.4 0.81-1.97 1.22-3.28 0.92-2.88 1.57-5.24 2.08-7.58 0.39-1.81 0.85-3.52 1.33-5.04 0.15-0.57 0.3-1.18 0.3-1.38 0-0.18 0.13-0.66 0.31-1.05 0.15-0.39 0.5-1.35 0.74-2.14 2.89-8.98 8.06-16.71 14.81-22.12 0.85-0.68 1.62-1.25 1.68-1.25 0.07 0 0.61-0.35 1.25-0.76 0.96-0.66 3.86-2.14 5.35-2.76 3.32-1.35 5.57-1.98 8.41-2.38 1.02-0.13 1.9-0.3 1.96-0.37 0.16-0.15 6.84 0.09 8.63 0.33zm1.42 13.13c1.44 0.85 2.34 1.68 3.63 3.34l0.96 1.24 0.13 1.31 0.15 1.31 0.33 0.14 0.33 0.1 0.43-0.37c0.64-0.56 1.09-1.74 1.23-3.12l0.13-1.2 0.76-0.37 0.77-0.37 2.51-0.14 2.51-0.13 0.33 0.22 0.32 0.22-0.39 0.66-0.37 0.63v1.35 1.34l0.57 0.76c0.65 0.85 0.59 1.22-0.29 1.66-5.28 2.66-9.17 5.9-9.58 7.99l-0.14 0.64 0.4 0.37 0.37 0.37 1.11-0.13c0.61-0.09 1.29-0.26 1.51-0.37 0.22-0.11 1.24-0.26 2.29-0.33l1.92-0.13 0.86 0.46c0.48 0.24 1.02 0.61 1.22 0.83l0.35 0.41 0.13 1.36 0.11 1.33-1.03 0.87c-0.54 0.48-1.31 1.16-1.68 1.51-0.37 0.33-1.09 0.96-1.62 1.38-3.25 2.62-6.15 7.09-7.16 11.03l-0.33 1.31-0.08 2.64-0.09 2.64 0.41 2.05c0.64 2.95 0.92 4.15 1.27 4.96 0.18 0.4 0.31 0.85 0.31 1.03 0 0.17 0.13 0.63 0.3 1.03 0.18 0.39 0.64 1.74 1.01 3.01 0.39 1.27 0.83 2.64 0.98 3.06 1.51 4.32 1.62 4.98 1.18 7.62-0.63 3.84-1.99 7.78-3.17 9.17l-0.57 0.68h-0.94-0.96l-0.63-0.79c-0.59-0.72-2.1-3.51-2.8-5.22-0.15-0.37-0.43-1.04-0.63-1.52-1.13-2.76-4.61-8.78-5.9-10.29-0.1-0.13-0.37-0.48-0.54-0.77-1.6-2.44-5.57-6.16-13.87-12.93-1.88-1.53-5.13-5-6.29-6.68-1.18-1.75-3.21-5.61-3.21-6.14 0-0.17-0.13-0.7-0.31-1.2-1.07-3.12-1.02-7.45 0.09-10.94 1.81-5.61 5.37-9.15 11.25-11.21l1.29-0.45h1.33c1.35 0 2.88 0.39 4.21 1.04 1.16 0.59 0.86 1.14-0.83 1.53-6.05 1.4-11.2 6.32-12.77 12.19l-0.37 1.33 0.11 2.6 0.1 2.6 0.33 1.11c1.31 4.4 4.35 8.13 10.03 12.32 3.05 2.27 2.99 2.21 4.43 3.39 1.01 0.81 1.94 1.62 3.71 3.27 0.81 0.75 2.95 3.57 2.95 3.87 0 0.11 0.35 0.74 0.79 1.4l0.79 1.18 0.21-0.13 0.22-0.13-0.11-0.7c-0.24-1.38-0.57-2.73-0.78-3.13-0.13-0.21-0.4-0.78-0.59-1.26-0.22-0.48-0.77-1.53-1.23-2.34l-0.85-1.44-1.9-1.95c-1.05-1.07-3.17-2.9-4.74-4.1-4.45-3.41-7.53-6.71-8.49-9.07-0.22-0.54-0.51-1.18-0.62-1.39-0.13-0.22-0.35-1.27-0.5-2.3l-0.26-1.88 0.28-1.63c1.03-5.94 7.26-11.21 13.89-11.73l1.45-0.11 1.18 0.39 1.15 0.37 2.08 0.03 2.07 0.02 1.64-0.64 1.64-0.63 1.14-1.16c1.13-1.13 1.55-1.96 1.28-2.6l-0.11-0.32-0.93 0.41c-0.53 0.22-1.6 0.81-2.41 1.29l-1.46 0.9-1.31 0.26-1.33 0.28-1.36-0.28c-1.55-0.31-2.16-0.61-3.89-1.88-0.65-0.5-2-1.42-2.99-2.05l-1.77-1.16 0.11-0.31c0.13-0.35 5.33-4.26 6.4-4.78 1.31-0.68 1.79-0.77 3.93-0.68l2.08 0.07zm19.35 3.62c0.35 0.18 0.81 0.33 1 0.33 0.55 0 4.33 1.75 5.75 2.64 0.37 0.22 0.81 0.48 0.98 0.57 1.92 0.85 6.77 6.12 7.32 7.89l0.15 0.52-0.52-0.15c-0.27-0.09-0.94-0.35-1.49-0.59-2.31-1.03-3.51-1.44-5.79-1.95l-1.31-0.3-4.26 0.02h-4.25l-0.88 0.24c-0.48 0.15-1.59 0.33-2.44 0.42l-1.6 0.15v-0.35-0.35l1.16-0.59c1.79-0.92 2.14-1.09 3.45-1.7 0.68-0.31 1.31-0.57 1.4-0.57 0.39 0 1.64-1.14 1.64-1.49 0-0.22-0.59-0.94-1.32-1.64-0.72-0.69-1.37-1.5-1.44-1.81l-0.13-0.52 0.35-0.55 0.35-0.54h0.63c0.35 0 0.92 0.15 1.25 0.32zm7.8 11.8c2.64 0.76 1.96 0.98-5.4 1.64-1.31 0.13-2.71 0.3-3.08 0.41l-0.7 0.2-0.32-0.2c-0.18-0.09-0.81-0.61-1.4-1.16l-1.05-0.98 0.31-0.11c0.74-0.26 2.07-0.3 6.13-0.24l4.28 0.09zm-83.21 33.66c0.22 0.69 0.54 1.57 0.7 1.94 0.15 0.35 0.43 1.05 0.65 1.53 1.66 3.93 8.43 14.5 10.86 16.95 0.17 0.17 0.41 0.46 0.52 0.65 0.99 1.71 11.73 12.91 15.05 15.71 0.61 0.5 1.33 1.13 1.64 1.39 0.3 0.27 1.16 0.94 1.9 1.51 0.74 0.57 1.48 1.16 1.64 1.31 0.43 0.39 4.43 3.15 5.52 3.8 1.25 0.74 7.54 3.78 7.82 3.78 0.18 0 0.53 0.17 0.79 0.37l0.46 0.39 0.13 0.9 0.13 0.9-0.35 0.32-0.35 0.35-1.94-0.02-1.95-0.02-0.72 0.76c-1.88 1.95-4.56 5.03-5.17 5.9l-0.31 0.44 0.11 1.46c0.09 1.57 0.48 4.48 0.83 6.27 0.13 0.59 0.3 1.77 0.41 2.62 0.22 1.77 0.68 4 1.1 5.24l0.26 0.88 3.49 3.42c1.92 1.9 4.11 3.98 4.85 4.66l1.38 1.2h0.54 0.53l2.07-1.9c1.14-1.05 3.26-3.08 4.7-4.55l2.66-2.62 0.33-1.2c0.2-0.65 0.46-1.79 0.59-2.51 0.13-0.72 0.37-2.14 0.57-3.17 0.17-1.02 0.41-2.44 0.52-3.16 0.11-0.72 0.29-1.75 0.42-2.3 0.13-0.54 0.24-1.81 0.24-2.84v-1.85l-1.68-1.97c-0.92-1.09-2.28-2.58-3-3.34l-1.31-1.35h-2.12-2.11l-0.24-0.31-0.24-0.28 0.13-1.05 0.15-1.03 0.52-0.63c0.31-0.35 0.64-0.64 0.72-0.64 1.16 0 8.52-7.25 8.52-8.38 0-0.07 0.29-0.53 0.64-1.05 1.35-1.99 3.91-7.62 4.47-9.81 0.31-1.24 0.57-1.48 0.99-0.98l0.26 0.33 0.19 2.47c0.11 1.35 0.31 3.34 0.44 4.43 0.26 2.51 0.26 15.2-0.02 17.36-0.11 0.9-0.31 2.65-0.42 3.89-0.1 1.22-0.26 2.34-0.32 2.45-0.09 0.13-0.22 0.98-0.33 1.92-0.11 0.92-0.31 2.07-0.42 2.55-0.1 0.48-0.37 1.66-0.59 2.63-0.19 0.96-0.48 2.14-0.63 2.62-0.15 0.48-0.46 1.5-0.65 2.29-0.2 0.79-0.48 1.66-0.59 1.97-0.13 0.3-0.31 0.83-0.42 1.2-0.09 0.35-0.5 1.59-0.92 2.73-0.41 1.13-0.83 2.27-0.91 2.51-0.09 0.24-0.42 1.11-0.77 1.96-0.35 0.83-0.67 1.69-0.74 1.86-0.07 0.18-0.22 0.48-0.31 0.66-0.11 0.17-0.37 0.72-0.59 1.2-0.19 0.48-0.45 1.02-0.56 1.2-0.22 0.39-0.96 1.94-1.16 2.4-0.07 0.18-0.48 0.92-0.9 1.64-0.41 0.72-0.85 1.51-0.96 1.75-0.85 1.96-7.27 11.64-8.32 12.55-0.09 0.07-0.81 0.94-1.64 1.97-3.25 3.98-9.37 10.09-12.99 12.97-1.82 1.47-7.84 6.03-7.95 6.03-0.05 0-1.18 0.75-2.51 1.64-1.36 0.9-2.49 1.64-2.56 1.64-0.07 0-0.44 0.24-0.81 0.52-0.39 0.31-0.94 0.64-1.24 0.77-0.31 0.13-0.9 0.46-1.31 0.7-1.23 0.74-4.39 2.42-5.03 2.68-0.17 0.07-0.72 0.37-1.2 0.68-0.48 0.28-1 0.52-1.16 0.55-0.15 0-0.63 0.24-1.09 0.52-0.76 0.48-2.01 1.05-5.94 2.75-2.71 1.18-2.9 1.27-3.93 1.64-0.55 0.2-1.27 0.5-1.59 0.68-0.35 0.17-0.79 0.3-1.01 0.3-0.2 0-0.48 0.11-0.61 0.24-0.13 0.13-0.57 0.31-0.96 0.42-0.42 0.11-1.29 0.39-1.95 0.65-0.65 0.27-1.48 0.55-1.85 0.66-0.88 0.24-2.1 0.68-2.56 0.89-0.22 0.11-0.74 0.29-1.2 0.4-0.46 0.11-1.16 0.3-1.53 0.43-0.39 0.14-1.05 0.35-1.42 0.48-0.39 0.14-1 0.31-1.37 0.42-0.88 0.24-3.21 1.07-4.37 1.55-0.24 0.09-0.98 0.39-1.64 0.66-1.42 0.54-2.49 1-3.34 1.42-0.35 0.17-0.7 0.3-0.81 0.3-0.11 0-0.94 0.44-1.83 0.98-0.92 0.55-1.73 0.99-1.77 0.99-0.31 0-3.65 2.46-5.2 3.82-2.14 1.88-3.47 3.34-5.13 5.66-0.68 0.93-1.62 2.14-2.1 2.66l-0.85 0.96h-1.49-1.48l-0.83-0.37c-2.41-1.05-2.86-1.31-3.67-2.12-0.77-0.76-1.18-1.44-2.3-3.6-0.11-0.2-0.32-0.88-0.52-1.53l-0.35-1.16v-2.42-2.41l-0.37-0.41-0.35-0.39h-1.03c-0.56 0-1.57-0.11-2.2-0.24-0.66-0.11-1.99-0.31-2.99-0.42-0.99-0.11-2.12-0.28-2.52-0.41-0.65-0.2-1.57-0.42-3.84-0.92-0.55-0.11-1.29-0.29-1.64-0.39-0.37-0.11-1.22-0.35-1.88-0.55-2.33-0.66-4.26-1.29-4.47-1.49-0.11-0.08-0.38-0.17-0.59-0.17-0.22 0-0.97-0.28-1.64-0.66-0.68-0.37-1.31-0.65-1.42-0.65-0.9 0-8.17-3.8-11.25-5.85-1.88-1.29-2.73-1.6-3.01-1.16-0.07 0.11-0.44 0.28-0.83 0.37-0.38 0.06-0.99 0.26-1.36 0.41-0.83 0.35-1.92 0.73-3.17 1.1-0.54 0.15-1.52 0.43-2.18 0.65-0.65 0.2-1.97 0.48-2.88 0.64l-1.71 0.28v-0.28c0-0.42 0.88-1.18 4.26-3.76 1.68-1.27 3.1-2.36 3.17-2.45 0.07-0.06 0.46-0.37 0.87-0.65 1.58-1.07 7.32-5.7 8.89-7.17 0.37-0.35 1.82-1.64 3.21-2.86l2.52-2.25 5.08-0.04 5.09-0.07 3.5-0.32c1.92-0.2 4.23-0.46 5.13-0.62 0.9-0.13 2.62-0.39 3.82-0.56 1.2-0.18 2.8-0.46 3.54-0.64 0.74-0.17 1.57-0.33 1.86-0.33 0.46 0 1.66-0.24 4.54-0.91 0.55-0.13 1.38-0.31 1.86-0.4 1.33-0.24 3.01-0.67 3.43-0.89 0.21-0.11 0.74-0.28 1.2-0.39 2.14-0.55 2.84-0.77 3.49-1.03 0.37-0.18 0.88-0.31 1.12-0.31 0.26 0 0.5-0.08 0.59-0.19 0.06-0.11 0.43-0.29 0.83-0.37 0.37-0.07 0.98-0.27 1.35-0.42 0.35-0.15 1.09-0.46 1.64-0.65 1.18-0.46 1.61-0.64 2.62-1.07 0.41-0.18 1.75-0.73 2.93-1.23 1.17-0.5 2.31-1 2.51-1.09 0.19-0.11 0.78-0.39 1.33-0.66 5.92-2.81 12.6-7.33 18.87-12.75 2.47-2.14 9.74-10.64 9.74-11.38 0-0.09 0.24-0.46 0.55-0.85 0.91-1.2 4.52-8.24 4.8-9.37 0.09-0.33 0.24-0.66 0.35-0.72 0.11-0.07 0.2-0.31 0.2-0.53 0-0.24 0.13-0.74 0.3-1.13 0.9-2.19 2.01-7.25 2.63-12.08 0.54-4.19 0.21-11.69-0.62-14.5-0.17-0.55-0.48-1.79-0.7-2.75-0.19-0.97-0.45-1.9-0.54-2.08-0.11-0.17-0.39-0.83-0.63-1.42-1.08-2.53-2.54-5.35-2.78-5.35-0.15 0-0.35 0.26-0.41 0.59l-0.16 0.59 0.29 1.22c0.46 1.99 0.89 4.79 1.11 7.1 0.11 1.2 0.31 2.86 0.44 3.71 0.13 0.83 0.28 2.69 0.35 4.11l0.13 2.58-0.37 3.86c-0.22 2.12-0.53 4.5-0.7 5.29-0.18 0.78-0.31 1.61-0.31 1.83 0 0.24-0.15 0.96-0.35 1.64-0.87 3.1-1.05 3.71-1.46 4.94-0.66 1.98-1 2.9-1.22 3.34-0.11 0.2-0.42 0.81-0.68 1.35-0.26 0.55-0.81 1.58-1.22 2.3-0.4 0.72-0.83 1.53-0.94 1.79-0.42 0.89-3.67 5.52-4.26 6.07-0.15 0.11-0.7 0.81-1.27 1.53-1.09 1.42-5.72 6-7.49 7.42-2.47 1.97-5.5 4.18-7.82 5.62-0.83 0.52-1.75 1.11-2.07 1.31-0.33 0.22-0.79 0.48-1.03 0.61-0.24 0.13-1.03 0.57-1.75 0.98-1.53 0.85-2.25 1.23-5.24 2.62-2.88 1.34-3.34 1.55-4.37 1.93-1.35 0.5-2.77 1.04-3.49 1.35-1.2 0.52-3.41 1.29-5.03 1.77-0.59 0.17-1.37 0.41-1.74 0.52-3.93 1.18-5.53 1.62-7.41 1.97-0.57 0.11-1.35 0.3-1.74 0.41-0.38 0.13-1.32 0.27-2.08 0.29l-1.4 0.06-0.08-0.24c-0.05-0.11 0.43-0.46 1.07-0.74 7.99-3.52 14.91-7.69 21.36-12.86 2.03-1.64 5.91-5.16 7.55-6.84l1.58-1.6 1.04-0.41c1.62-0.61 2.54-1 3.15-1.33 0.3-0.16 0.89-0.46 1.31-0.7 0.41-0.22 0.81-0.44 0.87-0.53 0.07-0.06 0.53-0.32 1.05-0.59 0.53-0.26 1.07-0.59 1.2-0.72 0.16-0.11 0.94-0.7 1.79-1.31 3.78-2.66 7.91-7.6 9.81-11.66 0.46-0.96 0.92-1.92 1.03-2.12 0.26-0.52 0.26-1.27-0.02-1.27-0.14 0-0.29 0.16-0.35 0.33-0.09 0.18-0.24 0.33-0.4 0.33-0.13 0-0.43 0.28-0.67 0.61-4.79 6.68-14.05 13.74-21.41 16.32-0.59 0.22-1.4 0.52-1.79 0.67-0.37 0.18-0.81 0.31-0.96 0.31-0.15 0-0.77 0.13-1.38 0.31-0.61 0.17-1.85 0.48-2.73 0.67l-1.64 0.35-4.71 0.13c-4.65 0.13-5.9 0.05-5.9-0.37 0-0.24 1.73-1.4 3.19-2.16 0.98-0.52 3.28-2.32 4.98-3.91 1.09-1 5.37-6.36 5.37-6.71 0-0.08 0.31-0.52 0.66-0.98 0.37-0.46 0.65-1.02 0.65-1.29v-0.46h-0.28c-0.15 0-1.47 1.16-2.91 2.56-3.6 3.56-6.59 6.14-7.73 6.68-0.39 0.2-0.81 0.46-2.4 1.49-1.25 0.81-3.15 1.75-5.24 2.6-0.66 0.26-1.4 0.59-1.64 0.72-0.24 0.13-0.79 0.3-1.2 0.39-0.42 0.09-1.16 0.26-1.64 0.39-0.48 0.11-1.62 0.38-2.51 0.57l-1.64 0.33h-2.51-2.51l-1.97-0.35c-1.07-0.17-2.05-0.41-2.16-0.52l-0.18-0.18 1.93-1.83c5.24-4.96 7.55-7.8 10.17-12.52 0.13-0.24 0.33-0.59 0.44-0.76 0.09-0.18 0.26-0.55 0.37-0.81 0.13-0.24 0.33-0.52 0.44-0.61 0.13-0.07 0.24-0.42 0.24-0.77v-0.61l-0.31-0.11c-0.35-0.13-0.78 0.24-0.78 0.66 0 0.15-0.09 0.28-0.18 0.28-0.11 0-0.43 0.35-0.74 0.77-2.1 2.95-10.46 11.29-14.15 14.08-0.55 0.42-1.03 0.81-1.1 0.9-0.13 0.15-3.82 2.93-4.91 3.69-0.44 0.31-0.92 0.66-1.05 0.77-0.37 0.32-5.07 3.4-6.33 4.17-0.59 0.35-1.33 0.8-1.64 1-0.33 0.22-0.74 0.46-0.92 0.55-0.17 0.08-1.16 0.65-2.18 1.26-1.03 0.62-2.34 1.38-2.95 1.69-0.59 0.3-1.64 0.87-2.29 1.24-0.66 0.37-2.34 1.22-3.72 1.9-1.37 0.68-2.66 1.31-2.84 1.42-0.17 0.11-0.54 0.31-0.83 0.42-0.28 0.11-1.07 0.48-1.74 0.78-1.64 0.79-3.91 1.82-4.85 2.23-0.42 0.17-0.94 0.41-1.14 0.5-0.61 0.31-2.14 0.85-3.25 1.16l-1.01 0.26-0.48-0.15-0.46-0.18v-0.76c0-0.39 0.16-1.03 0.33-1.35 0.18-0.35 0.33-0.79 0.33-0.99 0-0.17 0.15-0.52 0.33-0.76 0.17-0.22 0.32-0.59 0.32-0.81 0-0.24 0.14-0.68 0.31-0.98 0.18-0.33 0.96-1.92 1.77-3.54 0.79-1.62 1.53-3.1 1.64-3.28 5-8.36 4.74-7.9 5.81-9.5 1.4-2.09 1.92-2.84 2.12-2.9 0.08-0.05 0.15-0.18 0.15-0.31 0-0.13 0.28-0.59 0.63-1.03 0.33-0.43 1.27-1.76 2.08-2.97 0.81-1.2 2.62-3.71 4.02-5.61l2.55-3.45 0.33 0.07 0.33 0.06-0.05 0.53c-0.04 0.3-0.19 1.02-0.37 1.63-0.2 0.59-0.48 1.77-0.68 2.6l-0.34 1.51 0.37 1.18 0.37 1.18 0.81 0.63 0.83 0.66h1.37l1.4-0.02 1-0.7c0.57-0.4 1.64-1.27 2.41-1.97 1.74-1.62 7.27-6.84 8.08-7.64 0.33-0.33 1.02-0.94 1.55-1.36 3.01-2.42 5.33-4.23 6.25-4.87 0.56-0.41 1.52-1.11 2.14-1.57 2.86-2.14 9.3-5.68 14.06-7.71 0.42-0.18 1.14-0.48 1.6-0.68 0.45-0.19 1-0.35 1.2-0.35 0.22 0 0.48-0.08 0.61-0.19 0.2-0.18 2.16-0.81 4.67-1.47 0.79-0.19 1.84-0.5 2.36-0.65 0.5-0.18 1.12-0.31 1.36-0.31 0.21 0 0.63-0.09 0.91-0.19 0.29-0.11 1.44-0.42 2.58-0.68 1.14-0.26 2.51-0.61 3.06-0.77 0.54-0.15 1.57-0.45 2.29-0.65 0.72-0.2 1.62-0.5 2.01-0.68 0.37-0.17 0.81-0.3 0.96-0.3 0.15 0 0.68-0.14 1.18-0.31 0.48-0.17 1.46-0.48 2.19-0.68 0.72-0.22 1.61-0.52 2-0.7 0.38-0.15 0.73-0.28 0.79-0.28 0.15 0 2.71-1.16 4.52-2.05 0.79-0.37 2.4-1.34 3.61-2.12 1.2-0.79 2.42-1.57 2.73-1.73 1.37-0.72 8.08-7.88 8.08-8.62 0-0.16 0.41-0.66 0.94-1.16 0.19-0.2 0.37-0.53 0.37-0.72 0-0.2 0.15-0.42 0.33-0.51l0.32-0.1v-0.68-0.66h-0.41-0.42l-0.74 0.92c-0.7 0.87-3.36 3.54-4.46 4.48-0.26 0.22-0.98 0.85-1.59 1.42-0.63 0.59-1.22 1.05-1.29 1.05-0.09 0-0.41 0.24-0.72 0.52-0.85 0.79-3.25 2.42-4.8 3.25-2.17 1.18-2.62 1.4-3.91 1.97-0.66 0.31-1.66 0.74-2.23 1.01-0.57 0.24-1.16 0.45-1.31 0.45-0.15 0-0.48 0.16-0.7 0.33-0.24 0.18-0.59 0.33-0.81 0.33-0.2 0-0.65 0.15-0.98 0.33-0.35 0.17-0.9 0.32-1.22 0.32-0.33 0-0.64 0.09-0.7 0.2-0.07 0.11-0.51 0.26-0.94 0.33-0.46 0.09-1.23 0.28-1.71 0.44-1.09 0.37-2.86 0.87-4.69 1.33-0.79 0.19-1.71 0.43-2.08 0.54-0.35 0.11-1.2 0.29-1.85 0.42-0.66 0.11-1.49 0.3-1.82 0.44-0.35 0.13-0.89 0.24-1.24 0.24-0.35 0-0.68 0.08-0.74 0.19-0.09 0.11-0.55 0.26-1.07 0.35-1.14 0.18-3.08 0.72-4.02 1.12-0.37 0.17-0.83 0.3-1.01 0.3-0.17 0-0.61 0.15-0.94 0.33-0.35 0.17-0.81 0.33-1 0.33-0.2 0-0.42 0.08-0.5 0.19-0.07 0.11-0.44 0.29-0.83 0.37-0.88 0.18-1.53 0.46-5.07 2.19-4.13 2.01-6.09 3.12-9.72 5.52-2.45 1.6-6.2 4.33-7.54 5.46-0.37 0.31-1.2 1.01-1.85 1.56-2.34 1.96-3.91 3.42-7.65 7.12l-3.84 3.77-0.61 0.16-0.59 0.15-0.26-0.26-0.24-0.24 0.37-1.16c0.19-0.66 0.37-1.42 0.37-1.75 0-0.3 0.09-0.61 0.19-0.7 0.11-0.06 0.27-0.43 0.35-0.83 0.22-0.96 3.37-7.6 5.03-10.52 0.41-0.72 0.85-1.51 0.98-1.75 0.24-0.46 0.39-0.74 1.38-2.25 0.32-0.52 0.59-0.98 0.59-1.03 0-0.08 1.07-1.66 3.45-5.04 0.67-0.99 1.64-2.25 2.12-2.82 3.86-4.65 4.06-4.87 6.59-7.36 2.71-2.69 2.97-2.93 4.98-4.54 0.81-0.66 1.64-1.36 1.84-1.55 0.63-0.64 7.71-5.66 7.97-5.66 0.04 0 0.74-0.44 1.57-0.98 0.81-0.55 1.55-0.99 1.66-0.99 0.09 0 0.68-0.3 1.31-0.7 1.51-0.89 6.12-3.23 6.38-3.23 0.11 0 0.85-0.3 1.64-0.68 2.05-0.96 2.12-0.98 4.06-1.72 0.94-0.35 2.05-0.72 2.45-0.79 0.39-0.06 0.78-0.22 0.85-0.32 0.06-0.11 0.28-0.2 0.48-0.2 0.19 0 0.65-0.15 1-0.33 0.33-0.17 0.79-0.33 0.99-0.33 0.19 0 0.63-0.15 0.98-0.32 0.33-0.18 0.94-0.33 1.31-0.33 0.37 0 0.87-0.13 1.11-0.31 0.24-0.15 0.7-0.35 1.05-0.43 0.33-0.07 0.59-0.29 0.59-0.44 0-0.46-0.96-0.61-2.01-0.33-0.52 0.13-1.57 0.31-2.36 0.42-0.78 0.08-1.66 0.26-1.96 0.37-0.31 0.13-1.01 0.28-1.58 0.37-0.56 0.09-1.09 0.24-1.15 0.33-0.05 0.11-0.57 0.26-1.14 0.35-0.59 0.08-1.13 0.21-1.27 0.32-0.1 0.09-0.56 0.24-0.98 0.33-0.41 0.09-0.85 0.24-0.98 0.31-0.11 0.08-0.9 0.39-1.75 0.65-0.83 0.26-1.83 0.64-2.23 0.81-0.37 0.18-0.83 0.31-1.02 0.31-0.2 0-0.53 0.08-0.75 0.21-0.19 0.11-0.72 0.35-1.13 0.53-3.69 1.55-5.64 2.53-8.39 4.19-1.16 0.7-2.27 1.4-2.49 1.51-8.08 4.8-18 14.35-24.09 23.15-0.39 0.59-0.79 1.14-0.85 1.2-0.07 0.07-0.61 0.88-1.2 1.82-1.03 1.61-3.89 5.24-5.11 6.5-1.07 1.07-2.32 2.47-2.86 3.17-0.31 0.37-1.77 2.14-3.24 3.89-1.48 1.77-3.38 4.1-4.21 5.22-0.83 1.11-1.57 2.1-1.66 2.23-0.11 0.11-0.5 0.63-0.9 1.11-0.37 0.5-0.7 1.03-0.7 1.16 0 0.15-0.15 0.3-0.32 0.37-0.18 0.09-0.33 0.24-0.33 0.35 0 0.13-0.26 0.59-0.59 1.03-0.35 0.43-0.7 0.96-0.83 1.15-0.11 0.2-1.16 1.77-2.32 3.5-3.86 5.79-5.72 8.93-8.27 14.15-1.05 2.16-1.27 2.64-2.04 4.43-0.28 0.68-0.72 2.06-1.22 4-0.78 2.95 0.29 5.51 2.82 6.77 1.35 0.68 3.78 1.4 4.69 1.4 0.73 0 1.64 0.52 1.64 0.92 0 0.13-1.07 1.33-2.36 2.66-1.31 1.33-4.17 4.33-6.37 6.64-2.21 2.32-4.26 4.41-4.57 4.65-0.3 0.27-2.18 2.03-4.17 3.98-6.29 6.14-9.61 9.3-11.99 11.36-1.27 1.11-2.6 2.29-2.97 2.66-0.39 0.35-1.42 1.27-2.32 2.01-0.89 0.72-1.81 1.51-2.05 1.75-1.07 0.96-3.17 2.68-4.48 3.69-0.78 0.59-1.66 1.29-1.96 1.55-0.57 0.5-2.19 1.64-5.24 3.71-1.03 0.68-1.9 1.31-1.97 1.38-0.07 0.09-0.26 0.22-0.44 0.28-0.17 0.09-0.61 0.35-0.98 0.59-1.27 0.83-2.73 1.36-2.73 0.98 0-0.67 2.95-4.71 6.44-8.86 0.35-0.42 1.05-1.25 1.53-1.84 0.48-0.59 1.18-1.42 1.53-1.85 1.03-1.18 2.32-2.78 3.32-4.11 0.5-0.66 1.29-1.59 1.75-2.1 0.78-0.83 2.2-2.57 3.56-4.37 1.92-2.53 5.59-7.27 5.85-7.53 0.15-0.18 0.55-0.72 0.85-1.2 0.33-0.5 0.99-1.44 1.49-2.1 0.89-1.18 1.86-2.55 4.13-5.9 0.61-0.89 1.18-1.68 1.26-1.7 0.11-0.04 0.18-0.17 0.18-0.28 0-0.11 0.43-0.83 0.98-1.64 0.55-0.79 0.98-1.49 0.98-1.55 0-0.09 0.13-0.31 0.31-0.48 0.15-0.2 0.68-1.05 1.14-1.88 0.43-0.85 1-1.84 1.22-2.18 0.22-0.38 0.46-0.81 0.52-0.99 0.18-0.43 1.29-2.84 2.08-4.48 0.35-0.72 0.63-1.46 0.63-1.65 0-0.18 0.15-0.53 0.33-0.77 0.17-0.22 0.33-0.61 0.33-0.87 0-0.24 0.15-0.64 0.32-0.88 0.18-0.22 0.33-0.59 0.33-0.78 0-0.22 0.13-0.7 0.31-1.1 0.17-0.39 0.48-1.15 0.67-1.7 0.22-0.54 0.53-1.31 0.68-1.7 0.18-0.37 0.44-1.03 0.61-1.42 0.16-0.37 0.46-1.14 0.68-1.68 0.41-1.07 0.61-1.55 1.62-3.78 0.37-0.81 0.67-1.51 0.67-1.57 0-0.14 2.56-5.57 2.84-6.01 0.11-0.18 0.59-1.12 1.09-2.08 0.51-0.96 0.99-1.9 1.1-2.07 0.11-0.18 0.24-0.48 0.3-0.66 0.09-0.17 0.35-0.67 0.59-1.09 0.26-0.41 0.72-1.24 1.05-1.81 0.68-1.25 0.83-1.51 1.62-2.71 0.32-0.52 0.59-0.98 0.59-1.05 0-0.06 0.26-0.52 0.59-1.05 0.32-0.5 0.7-1.09 0.83-1.28 0.11-0.2 0.63-1.05 1.15-1.86 0.51-0.81 1.05-1.68 1.2-1.92 0.14-0.24 0.57-0.83 0.92-1.34 0.37-0.5 0.81-1.13 0.99-1.42 0.56-0.85 5.52-7.49 6.02-8.05 0.51-0.55 1.42-1.66 3.04-3.63 4.76-5.77 13.98-14.66 19.74-19.05 2.17-1.66 2.8-2.14 4.7-3.64 1-0.79 5.02-3.59 5.98-4.15 0.2-0.13 1.21-0.77 2.23-1.44 2.54-1.66 4.09-2.58 7.25-4.31 0.59-0.32 1.84-1 2.76-1.5 1.41-0.79 6.33-3.26 8.67-4.33 0.37-0.17 1.61-0.76 2.77-1.31 1.16-0.55 2.23-0.98 2.34-0.98 0.13 0 0.41-0.09 0.63-0.22 0.5-0.28 4-1.6 5.61-2.1 0.72-0.22 1.51-0.52 1.75-0.67 0.24-0.16 0.59-0.29 0.79-0.29 0.19 0 0.65-0.15 0.98-0.33 0.35-0.17 0.79-0.32 0.96-0.32 0.2 0 0.44-0.09 0.55-0.2 0.13-0.11 0.56-0.31 0.98-0.42 1.07-0.3 3.34-1.11 4.48-1.59 0.48-0.2 2.33-0.92 3.71-1.44 0.48-0.2 1.18-0.48 1.57-0.63 0.37-0.18 0.81-0.31 0.99-0.31 0.15 0 0.48-0.15 0.69-0.33 0.24-0.17 0.59-0.33 0.79-0.33 0.35 0 1.31-0.39 2.25-0.89 0.22-0.11 0.96-0.53 1.64-0.87 1.66-0.9 3.25-1.95 5.48-3.63 2.16-1.62 2.14-1.62 2.71 0.07zm54.6 54.03l0.2 0.18-0.81 1.65-0.83 1.66h-3.1-3.1l-0.31-0.39c-0.37-0.44-1.51-2.75-1.51-3.08 0-0.39 9.05-0.41 9.46-0.02zm-10.48 1.42c0.11 0.35 0.35 0.98 0.5 1.38 0.18 0.39 0.31 0.98 0.31 1.31v0.61l-0.94 1.07-0.96 1.07-1.55-0.77c-0.88-0.39-1.62-0.87-1.69-1.02l-0.11-0.26 1.71-2.08 1.68-2.05 0.44 0.04 0.43 0.04zm16.03 3.59c-0.08 0.5-2.94 1.85-3.49 1.63-0.35-0.13-1.9-2.42-1.9-2.79 0-0.44 0.87-2.36 1.29-2.84l0.35-0.39 1.9 2.03c1.05 1.13 1.9 2.18 1.85 2.36zm-6.46 0.52c0.76 0.74 1.44 1.57 1.77 2.23l0.3 0.57-0.39 2.22c-0.22 1.23-0.5 3.06-0.63 4.09-0.13 1.03-0.33 1.94-0.44 2.05-0.11 0.13-0.2 0.42-0.2 0.64v0.41l-1.9 1.83c-1.04 1.01-2.05 1.84-2.25 1.84-0.37 0-3.34-2.56-3.9-3.36-0.35-0.46-0.49-1.12-1.01-4.72-0.17-1.27-0.41-2.73-0.52-3.28-0.13-0.54-0.22-1.29-0.24-1.66v-0.68l1.26-1.33 1.25-1.35h3.19 3.19zm-12.76 2.01c0.59 0.28 1.25 0.7 1.44 0.92l0.35 0.41 0.22 1.51c0.13 0.85 0.37 2.47 0.57 3.6 0.17 1.14 0.39 2.45 0.48 2.88l0.13 0.83-0.52 0.44c-0.29 0.22-0.86 0.53-1.25 0.68l-0.74 0.24-0.22-0.22c-0.11-0.11-0.31-0.79-0.39-1.49-0.2-1.46-0.55-3.4-0.99-5.65-0.52-2.69-0.61-4.7-0.19-4.7 0.02 0 0.52 0.24 1.11 0.55zm19.59-0.37c0.07 0.11 0.02 0.72-0.09 1.37-0.13 0.66-0.28 1.58-0.34 2.06-0.35 2.66-1.42 8.01-1.64 8.27l-0.18 0.2-0.98-0.5c-0.57-0.26-1.11-0.68-1.25-0.92l-0.21-0.41 0.43-2.34c0.22-1.29 0.48-2.91 0.57-3.61 0.09-0.69 0.26-1.63 0.42-2.07l0.28-0.79 1.29-0.7c1.42-0.78 1.53-0.83 1.7-0.56zm-14.28 13.36c0.54 0.48 1.31 1.16 1.7 1.47 0.39 0.32 0.88 0.85 1.05 1.18l0.31 0.61v1.66 1.66l-0.31-0.07c-0.17-0.04-1.25-0.96-2.36-2.03-1.11-1.09-2.55-2.45-3.19-3.01-1.18-1.1-1.4-1.6-0.74-1.84 0.2-0.06 0.52-0.26 0.7-0.39 0.85-0.72 1.4-0.57 2.84 0.76zm10.79-0.63l0.78 0.46-0.43 0.61c-0.68 0.96-6.16 6.12-6.38 5.98-0.09-0.06-0.18-0.96-0.18-1.98v-1.88l1.05-1.01c0.57-0.54 1.44-1.37 1.97-1.83l0.92-0.81h0.74c0.41 0 1.11 0.2 1.53 0.46zm-125.46 19.59c0.55 0.15 1.79 0.42 2.8 0.59l1.79 0.33 2.36-0.02c1.29 0 2.84-0.09 3.43-0.2 0.61-0.13 1.61-0.28 2.25-0.35l1.13-0.15v0.3c0 0.24-2.25 1.95-3.89 2.93-0.19 0.13-0.96 0.59-1.66 1.05-0.69 0.46-1.48 0.94-1.74 1.05-0.27 0.11-0.81 0.41-1.23 0.65-2.01 1.23-3.99 2.25-7.09 3.69-1.08 0.51-2.6 1.23-3.39 1.6-1.92 0.89-2.51 1.13-5.57 2.27-0.48 0.17-1.16 0.44-1.53 0.59-0.81 0.33-4.83 1.59-6.38 2.01-3.95 1.07-5.24 1.37-6.61 1.61-0.55 0.11-1.27 0.29-1.6 0.42-0.35 0.13-0.94 0.24-1.33 0.24-0.39 0-1.01 0.11-1.38 0.22-0.83 0.3-3.99 0.83-6.68 1.13l-2.14 0.24-0.35-0.34-0.35-0.35 0.96-0.42c0.53-0.24 1.51-0.65 2.16-0.92 0.66-0.26 1.29-0.56 1.42-0.67 0.11-0.11 0.33-0.2 0.48-0.2 0.57 0 10.44-4.78 12.96-6.27 2.18-1.31 2.07-1.24 3.82-2.16 1.92-1.01 10-6.33 11.44-7.54 2.36-2.01 2.8-2.09 5.92-1.33zm35.38 0.57c0 1.35-12.16 10.18-18.67 13.5-2.64 1.35-5.22 2.64-5.94 2.95-0.39 0.15-1.09 0.45-1.53 0.65-0.46 0.2-1.11 0.48-1.48 0.63-0.35 0.14-1.01 0.42-1.42 0.59-0.92 0.4-2.06 0.79-2.95 1.03-0.85 0.24-1.99 0.63-2.91 1.01-0.39 0.17-0.94 0.3-1.2 0.3-0.26 0.02-0.72 0.15-1.03 0.33-0.3 0.17-0.76 0.3-1.04 0.33-0.29 0-0.97 0.13-1.53 0.3-3.02 0.9-7.41 1.12-13.96 0.7-3.01-0.2-6.36-0.35-7.43-0.37-1.04 0-2.11-0.09-2.33-0.17l-0.42-0.16 0.77-0.48c0.41-0.26 1.05-0.48 1.37-0.48 0.33 0 1.29-0.15 2.17-0.33 0.85-0.19 2.29-0.5 3.18-0.67 1.6-0.33 3.11-0.72 4.92-1.29 0.48-0.16 1.46-0.44 2.18-0.66 0.72-0.22 1.64-0.52 2.03-0.67 0.4-0.18 0.9-0.31 1.14-0.31 0.22 0 0.46-0.09 0.55-0.2 0.06-0.11 0.43-0.28 0.83-0.37 0.37-0.06 1.04-0.28 1.46-0.48 0.81-0.35 0.94-0.39 2.84-1.16 0.65-0.26 2.71-1.2 4.52-2.09 1.83-0.88 3.43-1.6 3.56-1.6 0.11 0 0.22-0.08 0.22-0.19 0-0.11 0.26-0.31 0.61-0.44 0.7-0.26 3.49-1.81 4.74-2.62 0.48-0.31 0.98-0.61 1.09-0.68 0.13-0.06 0.94-0.61 1.81-1.2 0.9-0.61 1.77-1.2 1.97-1.31 0.22-0.13 0.81-0.57 1.33-0.98 0.55-0.42 1.33-0.99 1.75-1.27 0.41-0.28 1.05-0.79 1.38-1.11l0.61-0.57 6.83-0.02h6.82l0.98-0.35c0.55-0.2 1.25-0.35 1.59-0.37l0.59-0.03zm-69.01 24.97c0.17 0.04 1.31 0.17 2.51 0.28 1.2 0.11 3.12 0.31 4.26 0.42 1.13 0.13 2.99 0.24 4.1 0.24h2.03l-0.06 0.48-0.07 0.48-1.31 1.07c-0.72 0.59-2.49 2.01-3.93 3.17-1.44 1.15-2.66 2.16-2.73 2.25-0.06 0.06-0.78 0.65-1.64 1.31-0.83 0.63-1.72 1.33-1.98 1.55-1.31 1.15-11.19 8.67-13.26 10.11-0.68 0.48-2.05 1.44-3.06 2.14-0.98 0.7-2.42 1.72-3.21 2.25-0.79 0.54-2.16 1.48-3.08 2.12-0.92 0.63-1.81 1.22-1.99 1.35-0.19 0.11-1.46 0.96-2.81 1.88-2.17 1.44-3.04 2.01-4.96 3.15-0.2 0.13-0.96 0.61-1.68 1.09-1.64 1.07-2.1 1.35-2.52 1.55-0.26 0.13-2.64 1.5-3.93 2.27-2.16 1.29-4.58 2.12-4.58 1.57 0-0.19 0.78-1.02 1.66-1.79 0.34-0.3 1.33-1.13 2.16-1.88 0.85-0.72 1.79-1.5 2.12-1.77 0.32-0.24 1.15-0.94 1.85-1.55 0.7-0.61 1.77-1.53 2.36-2.03 4.81-4.04 9.26-8.25 19.44-18.43 3.36-3.37 6.6-6.71 7.21-7.43 1.02-1.27 2.58-2.97 4.65-5.17l0.96-1.05 0.59 0.13c0.31 0.06 0.72 0.17 0.9 0.24zm91.38 28.5c-0.07 0.28-0.79 1.22-1.59 2.12-3.02 3.34-5.18 6.77-6.8 10.72-0.67 1.66-1 2.1-1.85 2.49l-0.72 0.35h-1.53-1.55l-0.83-0.48c-1.93-1.11-4.87-5.15-4.87-6.7v-0.66l0.72-0.52c0.37-0.29 1.22-0.79 1.87-1.12 0.66-0.35 1.36-0.7 1.53-0.78 0.83-0.44 3.32-1.53 3.5-1.53 0.11 0 0.48-0.13 0.83-0.31 0.33-0.17 0.98-0.46 1.44-0.65 0.44-0.2 1.14-0.48 1.53-0.66 0.37-0.15 1.13-0.46 1.68-0.67 0.55-0.2 1.31-0.51 1.7-0.68 0.4-0.18 0.88-0.31 1.05-0.31 0.2 0 0.66-0.13 1.03-0.3 0.68-0.29 2.16-0.7 2.73-0.77l0.28-0.02zm-22.14 12.78c0.98 1.61 1.98 3.1 2.79 4.1 0.09 0.11 0.46 0.66 0.83 1.2 0.37 0.55 1.12 1.62 1.64 2.41 0.55 0.78 1.05 1.57 1.14 1.74 0.08 0.18 0.24 0.49 0.37 0.66 0.48 0.74 3.34 5.59 3.53 6.01 0.22 0.45 0.42 0.8 1.29 2.18 0.31 0.48 0.64 1.03 0.7 1.2 0.09 0.18 0.46 0.81 0.83 1.42 0.35 0.59 0.81 1.38 0.99 1.75 0.17 0.35 0.65 1.24 1.07 1.96 1.41 2.54 2.11 3.94 2.4 4.9l0.3 0.94-0.19 0.52c-0.31 0.76-0.96 1.33-2.36 2.03-1.2 0.61-1.66 0.83-4.52 2.1-0.72 0.3-1.58 0.72-1.9 0.89l-0.57 0.31h-1.4-1.4l-1.18-0.42c-1.94-0.69-2.53-1.07-3.77-2.4l-1.18-1.29-0.33-0.94c-0.18-0.52-0.57-1.66-0.83-2.49-0.29-0.85-0.64-1.83-0.79-2.22-0.17-0.38-0.3-0.88-0.3-1.1 0-0.21-0.09-0.5-0.22-0.63-0.11-0.11-0.31-0.65-0.42-1.18-0.11-0.54-0.3-1.29-0.41-1.64-0.13-0.37-0.4-1.24-0.59-1.96-0.31-1.2-0.55-2.03-1.31-4.7q-0.79-2.74-1.31-4.69c-0.2-0.72-0.46-1.62-0.59-1.97-0.13-0.37-0.29-1.07-0.33-1.57l-0.11-0.94 0.63-0.81c0.35-0.46 0.77-1.05 0.94-1.29 0.57-0.83 3.13-4.1 3.48-4.48 0.19-0.19 0.56-0.61 0.83-0.93 0.76-0.88 1-0.73 2.25 1.33zm13.08 5.15c0.13 0.18 0.72 1.23 1.31 2.36 0.57 1.14 1.31 2.49 1.64 3.04 0.3 0.54 0.63 1.13 0.72 1.31 0.09 0.17 0.57 1.02 1.07 1.88 0.5 0.87 1.29 2.25 1.75 3.05 1.22 2.25 1.37 2.54 1.83 3.26 0.24 0.35 0.52 0.85 0.66 1.09 0.13 0.24 0.41 0.72 0.65 1.09 0.24 0.35 0.52 0.85 0.66 1.09 0.13 0.24 0.39 0.7 0.61 1.03 0.19 0.33 0.76 1.2 1.22 1.97 4.28 6.9 5.64 8.23 10.29 10.24 2.2 0.94 7.05 1.48 13.65 1.51 6.9 0.04 10.09 0.46 12.49 1.63 1.31 0.64 2.32 1.53 2.05 1.8-0.06 0.08-5.87 0.13-12.86 0.08l-12.71-0.04-1.31-0.33c-2.01-0.5-3.65-1-4.41-1.33-0.38-0.15-0.79-0.28-0.92-0.28-0.22 0-1.29-0.44-2.43-0.99-2.59-1.22-5.7-1.66-9.93-1.37l-1.95 0.15-0.28-0.24c-0.46-0.37-0.35-0.55 0.74-1.07 0.55-0.26 1.62-1.09 2.38-1.84l1.38-1.33 0.06-1.09c0.09-1.44-0.13-3.52-0.48-4.46-0.39-1-2.33-4.95-2.86-5.78-0.22-0.37-0.5-0.86-0.63-1.1-0.11-0.24-0.31-0.59-0.42-0.76-0.48-0.76-2.14-3.63-2.27-3.93-0.09-0.18-0.35-0.63-0.59-0.98-0.24-0.38-0.52-0.86-0.63-1.1-0.11-0.24-0.98-1.74-1.97-3.32-0.96-1.59-1.94-3.27-2.18-3.75l-0.44-0.85 0.26-0.24c0.53-0.42 1.36-0.66 2.47-0.66l1.14-0.02zm-26.54 1.94l1.27 0.24 0.41 0.96c0.22 0.55 0.42 1.18 0.42 1.42 0 0.26 0.15 1.01 0.35 1.68 0.17 0.68 0.48 1.77 0.65 2.43 0.2 0.65 0.46 1.68 0.64 2.29 0.15 0.59 0.45 1.73 0.65 2.51 0.22 0.79 0.53 1.88 0.68 2.45 0.17 0.59 0.44 1.51 0.61 2.08 0.87 3.05 1.07 3.73 1.31 4.32 0.37 0.9 0.79 2.05 1.01 2.84 0.1 0.35 0.39 1.2 0.65 1.86 0.26 0.65 0.52 1.39 0.59 1.63 0.2 0.68 1.51 2.58 2.21 3.21 0.69 0.62 4.63 2.58 5.15 2.58 0.18 0 0.66 0.13 1.05 0.31 0.39 0.17 1.55 0.46 2.58 0.65l1.85 0.35h7.49 7.52l1.22 0.35c2.43 0.68 4.67 2.12 4.28 2.73l-0.11 0.2-12.71-0.02h-12.71l-1.09-0.2c-0.59-0.11-1.58-0.26-2.19-0.35-1.02-0.11-2.31-0.46-4.04-1.07-3.54-1.24-5.15-1.24-8.73 0-0.42 0.15-1.45 0.44-2.3 0.61l-1.53 0.35-2.99 0.09c-1.66 0.04-3.12 0-3.25-0.07l-0.24-0.17 0.13-0.44c0.17-0.52 2.29-2.01 2.9-2.01 0.22-0.02 0.64-0.15 0.94-0.33 0.31-0.17 0.85-0.3 1.2-0.32 0.7 0 2.47-0.51 3.45-1.01 0.35-0.17 0.72-0.3 0.83-0.3 0.14 0 0.75-0.4 1.38-0.88l1.14-0.87 0.45-0.92c0.27-0.52 0.59-1.42 0.75-2.01l0.26-1.07-0.37-1.66c-0.22-0.92-0.53-2.18-0.7-2.82-0.18-0.61-0.44-1.66-0.61-2.29-0.18-0.61-0.46-1.7-0.66-2.4-0.17-0.68-0.48-1.77-0.65-2.4-0.42-1.55-1.01-3.59-1.34-4.63-0.13-0.48-0.43-1.47-0.63-2.19-0.22-0.72-0.52-1.75-0.68-2.29-0.17-0.55-0.37-1.31-0.43-1.68-0.09-0.4-0.24-0.77-0.35-0.83-0.11-0.09-0.2-0.4-0.2-0.72-0.02-0.33-0.15-0.83-0.33-1.14-0.17-0.31-0.3-0.72-0.32-0.94v-0.37h0.94c0.52 0 1.52 0.11 2.2 0.26z"/>
27
+ <path class="s1" d="m284.02 22.01c-1.15 0.48-2.29 1.46-2.77 2.38l-0.35 0.7v1.07c0 5.24 8.23 6.14 9.06 0.98l0.16-0.91-0.27-1.2-0.24-1.23-0.67-0.65c-1.42-1.42-3.19-1.84-4.92-1.14zm1.12 1.81l0.57 0.44v0.46c0 1.07-0.94 1.53-1.86 0.92l-0.55-0.35v-0.53c0-0.5 0.68-1.39 1.07-1.39 0.09 0 0.44 0.19 0.77 0.45z"/>
28
+ </g>
29
+ </g>
30
+ <g>
31
+ <path class="s2" d="m36.98 288h11.03v34.49l36.62-34.49h14.22l-40.49 38.04 43.38 43.56h-14.53l-39.2-39.3v39.3h-11.03zm112.45 0h12.52l31.09 81.6h-11.47l-7.43-20.93h-36.78l-7.43 20.93h-11.65zm6.24 10.88l-14.98 40.6h30zm64.02-10.87h28.22q12.62 0 19.44 5.24 6.83 5.25 6.83 14.92 0 7.5-3.5 11.93-3.49 4.42-10.27 5.51 8.15 1.75 12.66 7.31 4.51 5.54 4.51 13.84 0 10.94-7.44 16.9-7.43 5.95-21.16 5.95h-29.29zm11.04 9.07v24.59h16.35q8.08 0 12.03-3.02 3.97-3.04 3.97-9.27 0-6.17-3.97-9.23-3.95-3.07-12.03-3.07zm0 33.57v29.88h17.71q8.9 0 13.19-3.69 4.31-3.69 4.31-11.27 0-7.67-4.31-11.28-4.29-3.64-13.19-3.64zm73.5-42.64h11.04v34.49l36.62-34.49h14.22l-40.5 38.04 43.38 43.56h-14.53l-39.19-39.3v39.3h-11.04z"/>
32
+ </g>
33
+ </svg>
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Parham Taheri
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,112 @@
1
+ <h1 align="center">
2
+ <img src="https://raw.githubusercontent.com/par-taheri/Kabk/main/Kabk_logo.svg" alt="Kabk Logo" width="200" />
3
+ </h1>
4
+
5
+ <p align="center">
6
+ <a href="https://rubygems.org/gems/kabk"><img src="https://img.shields.io/gem/v/kabk.svg?color=blue" alt="Gem Version"></a>
7
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
8
+ </p>
9
+
10
+ > **Kabk carries the Ruby to Simorgh**
11
+
12
+ The framework-agnostic Ruby backend engine designed exclusively to power the Simurgh Panel.
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 'kabk'
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ This gem manages the metadata registry, schema manifest generation, server-side validation, pagination, query filtering, and concurrency control. Kabk is ORM-agnostic and relies on the Adapter pattern to interface with your database (e.g., via Sequel). It operates entirely on plain Ruby hashes and assumes your host application (like Roda or Rails) handles authentication and authorization.
25
+
26
+ ### Registering a Resource
27
+
28
+ ```ruby
29
+ require 'kabk'
30
+
31
+ # Assuming you have a Sequel Model
32
+ class NewsItem < Sequel::Model; end
33
+
34
+ # Kabk automatically detects Sequel models and uses the Kabk::Adapters::SequelAdapter
35
+
36
+ Kabk.register(name: 'news_item', table: NewsItem) do
37
+ title fa: 'اخبار و اطلاعیه‌ها', en: 'News & Announcements'
38
+ icon 'Newspaper'
39
+ plural_name 'news'
40
+ api_path '/api/admin/news'
41
+
42
+ # Concurrency & Auditing (created_by and updated_by are auto-injected from context[:current_user_id])
43
+ concurrency_field 'updated_at'
44
+ audit_fields %w[created_by updated_by created_at updated_at]
45
+
46
+ field :id, type: :number, form_type: :number, primary_key: true, hidden_in_form: true
47
+ field :title, type: :string, form_type: :text, required: true, validation: { min_length: 5, unique: true }
48
+ field :content, type: :string, form_type: :wysiwyg
49
+ field :publish_date, type: :datetime, form_type: :datetime, calendar: :jalali
50
+
51
+ # Lifecycle Hooks
52
+ after_create do |record, context|
53
+ # trigger background job
54
+ end
55
+ end
56
+ ```
57
+
58
+ ### Generic REST Engine
59
+
60
+ The `Kabk::RestEngine` class orchestrates validation, unique checks, audit field injections, and delegates CRUD operations to the configured ORM adapter. It returns standardized raw hashes that your HTTP layer can easily convert to JSON.
61
+
62
+ ```ruby
63
+ engine = Kabk::RestEngine.new('news_item')
64
+
65
+ # Pagination, Filtering (exact, IN, range), Sorting, and Hydration are automatic
66
+ result = engine.list({
67
+ "page" => 1,
68
+ "per_page" => 15,
69
+ "sort" => "-created_at",
70
+ "filter" => { "publish_date" => { "gte" => "2026-01-01" } }
71
+ }, context: { current_user_id: 1 })
72
+ # => { success: true, data: [...], meta: { ... } }
73
+
74
+ # Validation, Uniqueness, and OCC automatically applied
75
+ result = engine.update(1, { "title" => "New Title", "updated_at" => "2026-03-15T11:00:00Z" }, context: { current_user_id: 1 })
76
+ ```
77
+
78
+ ### System Configuration (Protocol v1.6.0)
79
+
80
+ Kabk generates a JSON schema manifest containing dynamic system configuration and UI settings. You can override these defaults by passing a custom hash to the `SchemaRenderer`. Ensure you inject your authentication endpoints here, as Kabk itself does not provide them.
81
+
82
+ ```ruby
83
+ renderer = Kabk::SchemaRenderer.new(
84
+ system_config: {
85
+ title: { fa: "پنل مدیریت", en: "My Custom Admin" },
86
+ logo_url: "/custom-logo.png",
87
+ endpoints: {
88
+ upload: "/api/files"
89
+ },
90
+ auth: {
91
+ strategy: "session",
92
+ sso_redirect_url: nil,
93
+ login_url: "/auth/admin_login",
94
+ me_url: "/auth/admin_me",
95
+ logout_url: "/auth/admin_logout",
96
+ refresh_url: "/auth/admin_refresh",
97
+ login_fields: [
98
+ { name: "email", label: { en: "Email", fa: "ایمیل" }, type: "text", required: true },
99
+ { name: "password", label: { en: "Password", fa: "کلمه عبور" }, type: "password", required: true }
100
+ ]
101
+ }
102
+ }
103
+ )
104
+ schema = renderer.render
105
+ ```
106
+
107
+ ## Testing
108
+
109
+ ```bash
110
+ bundle install
111
+ bundle exec rspec
112
+ ```