xenos-enigma 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +6 -0
- data/LICENSE +21 -0
- data/README.md +159 -0
- data/bin/xenos-enigma +4 -0
- data/lib/xenos_enigma.rb +1 -0
- data/lib/xenos_enigma/default_data.rb +56 -0
- data/lib/xenos_enigma/hit_collector.rb +62 -0
- data/lib/xenos_enigma/radar.rb +67 -0
- data/lib/xenos_enigma/runner.rb +34 -0
- data/lib/xenos_enigma/version.rb +3 -0
- data/lib/xenos_enigma/xenos/aeldari.rb +18 -0
- data/lib/xenos_enigma/xenos/base.rb +61 -0
- data/lib/xenos_enigma/xenos/tau.rb +18 -0
- data/spec/base_spec.rb +61 -0
- data/spec/helpers/randomize.rb +9 -0
- data/spec/hit_collector_spec.rb +37 -0
- data/spec/radar_spec.rb +47 -0
- metadata +82 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3f9f61779f252a914d06bd33dcb744b4077b0eff04c7fbe59a383d9373e2fd5f
|
4
|
+
data.tar.gz: 0b44c9aad8ba9ac1ee81f41f467bb85eb509884e738e86e52fbcad4051840335
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 810f480098060ab33000490998d81551d73cd3cd1c1b2df0a6ee7269b8d4d62a568d09aaae6edadeed5620459c05471f95ace4a5b4284e75143500a38f47963f
|
7
|
+
data.tar.gz: e63c6eb11e3a310e66a2334bce37be61b4a46ae14a2cfe6dc56d3d10cd43b6ac2aab245c8feec2716086929da984e6a322318c71cd14f674465dd568eeb95ca6
|
data/CHANGELOG
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2021 Haris Krajina
|
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,159 @@
|
|
1
|
+
# Xenos Enigma
|
2
|
+
|
3
|
+
## Description:
|
4
|
+
|
5
|
+
In the grim dark future of 40k, there is only war and humanity is under threat again. There are Xenos forces emerging from deep space and the order of Adeptus Mechanicus has been tasked with creating advanced radar systems to detect these threats before it is too late.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
```bash
|
10
|
+
gem install xenos-enigma
|
11
|
+
```
|
12
|
+
|
13
|
+
## Run
|
14
|
+
|
15
|
+
```
|
16
|
+
xenos-enigma --help
|
17
|
+
Usage: bin/run [--path FILE]
|
18
|
+
--help show help
|
19
|
+
--path FILE set path to radar data file, uses default data if no file provided
|
20
|
+
```
|
21
|
+
|
22
|
+
## Development
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
bundle install # install development dependencies
|
26
|
+
bin/xenos-enigma # run executable
|
27
|
+
rspec # run test suite
|
28
|
+
```
|
29
|
+
|
30
|
+
## Known xenos:
|
31
|
+
#### Tau
|
32
|
+
~~~~
|
33
|
+
--o-----o--
|
34
|
+
---o---o---
|
35
|
+
--ooooooo--
|
36
|
+
-oo-ooo-oo-
|
37
|
+
ooooooooooo
|
38
|
+
o-ooooooo-o
|
39
|
+
o-o-----o-o
|
40
|
+
---oo-oo---
|
41
|
+
~~~~
|
42
|
+
#### Aeldari
|
43
|
+
~~~~
|
44
|
+
---oo---
|
45
|
+
--oooo--
|
46
|
+
-oooooo-
|
47
|
+
oo-oo-oo
|
48
|
+
oooooooo
|
49
|
+
--o--o--
|
50
|
+
-o-oo-o-
|
51
|
+
o-o--o-o
|
52
|
+
~~~~
|
53
|
+
|
54
|
+
#### Radar sample:
|
55
|
+
~~~~
|
56
|
+
----o--oo----o--ooo--ooo--o------o---oo-o----oo---o--o---------o----o------o-------------o--o--o--o-
|
57
|
+
--o-o-----oooooooo-oooooo---o---o----o------ooo-o---o--o----o------o--o---ooo-----o--oo-o------o----
|
58
|
+
--o--------oo-ooo-oo-oo-oo-----O------------ooooo-----oo----o------o---o--o--o-o-o------o----o-o-o--
|
59
|
+
-------o--oooooo--o-oo-o--o-o-----oo--o-o-oo--o-oo-oo-o--------o-----o------o-ooooo---o--o--o-------
|
60
|
+
------o---o-ooo-ooo----o-----oo-------o---oo-ooooo-o------o----o--------o-oo--ooo-oo-------------o-o
|
61
|
+
-o--o-----o-o---o-ooooo-o-------oo---o---------o-----o-oo-----------oo----ooooooo-ooo-oo------------
|
62
|
+
o-------------ooooo-o--o--o--o-------o--o-oo-oo-o-o-o----oo------------o--oooo--ooo-o----o-----o--o-
|
63
|
+
--o-------------------------oo---------oo-o-o--ooo----oo----o--o--o----o--o-o-----o-o------o-o------
|
64
|
+
-------------------o----------o------o--o------o--------o--------o--oo-o-----oo-oo---o--o---o-----oo
|
65
|
+
----------o----------o---o--------------o--o----o--o-o------------oo------o--o-o---o-----o----------
|
66
|
+
------o----o-o---o-----o-o---o-----oo-o--------o---------------------------------o-o-o--o-----------
|
67
|
+
---------------o-------o-----o-------o-------------------o-----o---------o-o-------------o-------oo-
|
68
|
+
-o--o-------------o-o-----o--o--o--oo-------------o----ooo----o-------------o----------oo----o---o-o
|
69
|
+
-o--o-------------o----oo------o--o-------o--o-----o-----o----o-----o--o----o--oo-----------o-------
|
70
|
+
-o-----oo-------o------o----o----------o--o----o-----o-----o-------o-----------o---o-o--oooooo-----o
|
71
|
+
-o--------o-----o-----o---------oo----oo---o-o---------o---o--oooo-oo--o-------o------oo--oo--o-----
|
72
|
+
------------o---------o---------o----oooo-------------oo-oo-----ooo-oo-----o-------o-oo-oooooooo---o
|
73
|
+
----------------------o------------oooooooo---o-----o-------o--oooooo-o------------o-o-ooooooo-o----
|
74
|
+
------------o------o---o---o-------oo-oo--o--o---------o--o-o-o-ooooo-o--------------oo-o----o-oo-o-
|
75
|
+
---o-o----------oo-------oo----o----oooooooo-------o----o-o-o-o-----o-o-----o----------ooo-oo--o---o
|
76
|
+
-o-o---------o-o---------------o--o--o--ooo---ooo-------o------oo-oo------------o--------o--o-o--o--
|
77
|
+
-------oo---------------------------o-oo----------o------o-o-------o-----o----o-----o-oo-o-----o---o
|
78
|
+
---o--------o-----o-------o-oo-----oo--oo-o----oo----------o--o---oo------oo----o-----o-------o-----
|
79
|
+
---o--ooo-o---------o-o----o------------o---------o----o--o-------o----o--------o----------------oo-
|
80
|
+
---o------o----------------o----o------o------o---oo-----------o-------------o----------oo---------o
|
81
|
+
--oo---------------o--o------o---o-----o--o-------------o------o-------o-----o-----o----o------o--o-
|
82
|
+
-o-------o----------o-o-o-------o-----o--o-o-----------o-oo-----------o------o---------o-----o-o----
|
83
|
+
----------o----o-------o----o--o------o------------o---o---------------oo----o-----ooo--------------
|
84
|
+
----o--------oo----o-o----o--o------ooo----o-oooo---o--o-oo--------o-oo-----o-o---o-o--o-----oo-----
|
85
|
+
------o--------o-ooooo----o---o--o-----o---------------o-o-------o-----o----------------------------
|
86
|
+
o-------oo----o--oooooo-o---o--o------oooo----------o-oo-------o---o----------o------oo-------------
|
87
|
+
-o---o----------o--oo-oo-o---o-----o-o-----------------------oo--o------o------o--------------------
|
88
|
+
-----oo-o-o-o---ooooooooo----o----o--------o--o---oo---o------------o----------o-o---o------o-o--oo-
|
89
|
+
------o------o---ooo-o---------------------------o--o---o---o----o--o-------o-----o------o----o----o
|
90
|
+
-------o----------ooo-o-----o----o---o--o-oo--o--o-o--o------o--o-oo---ooo------------------------o-
|
91
|
+
-o-------o------o-o--ooo--o---o---oo-----o----o-------------o----o-ooo-o------o--o-o------o-o-------
|
92
|
+
---oo--o---o-o---------o---o--------------o--o-----o-------o-----o--o---o-oo--------o----o----o-----
|
93
|
+
o------o----oo-o-----------oo--o---o--------o-o------o-------o-o------o-oo---------o-----oo---------
|
94
|
+
----o--o---o-o-----------o---o------------o-------o----o--o--o--o-o---------------o-----------------
|
95
|
+
-------oo--o-o-----o-----o----o-o--o----------------------o-------o------o----oo----ooo---------o---
|
96
|
+
o-----oo-------------------o--o-----o-----------o------o-------o----o-----------o----------------o--
|
97
|
+
--o---o-------o------------o--------------------o----o--o-------------oo---o---------oo--------o----
|
98
|
+
--o--------o---------o------------o------o-------o------------o-------o---o---------ooooo-----------
|
99
|
+
------o--------------o-o-o---------o---o-------o--o-----o-------o-o----------o-----oo-ooo----------o
|
100
|
+
--o---------------o----o--oo-------------o---------o-------------------oo---------oo-o-ooo----------
|
101
|
+
-o-----------o------ooo----o----------------ooo-----o--------o--o---o-----------o-o-oooooo--------oo
|
102
|
+
-o---o-------o---o-oooo-----o-------------------o----oo-----------------o--o--------o--o------o--o--
|
103
|
+
-------o---o------oooooo--o----ooo--o--------o-------o----------------------------oo-oo-o--o--------
|
104
|
+
o--oo------o-----oo--o-oo------------oo--o------o--o-------------oo----o------------oooo-o------oo--
|
105
|
+
-----o----------ooooooooo--------------oo--------------oo-----o-----o-o--o------o----------o----o---
|
106
|
+
~~~~
|
107
|
+
#### Radar echo:
|
108
|
+
~~~~
|
109
|
+
--------------------oooo---------------------oo-----------------------------------------------------
|
110
|
+
-------------------oooooo-------------------oooo----------------------------o-----o-----------------
|
111
|
+
------------------oo-oo-oo-----------------oooooo----------------------------o---o------------------
|
112
|
+
------------------oooooooo----------------oo-oo-oo--------------------------ooooooo-----------------
|
113
|
+
--------------------o--o------------------oooooooo-------------------------oo-ooo-oo----------------
|
114
|
+
-------------------o-oo-o-------------------o--o--------------------------ooooooooooo---------------
|
115
|
+
------------------o-o--o-o-----------------o-oo-o-------------------------o-ooooooo-o---------------
|
116
|
+
------------------------------------------o-o--o-o------------------------o-o-----o-o---------------
|
117
|
+
-----------------------------------------------------------------------------oo-oo------------------
|
118
|
+
----------------------------------------------------------------------------------------------------
|
119
|
+
----------------------------------------------------------------------------------------------------
|
120
|
+
----------------------------------------------------------------------------------------------------
|
121
|
+
---------------------------------------------------------------------------------------o-----o------
|
122
|
+
--------------------------------------------------------------o-----o-------------------o---o-------
|
123
|
+
---------------------------------------------------------------o---o-------------------ooooooo------
|
124
|
+
--------------------------------------oo----------------------ooooooo-----------------oo-ooo-oo-----
|
125
|
+
-------------------------------------oooo--------------------oo-ooo-oo---------------ooooooooooo----
|
126
|
+
------------------------------------oooooo------------------ooooooooooo--------------o-ooooooo-o----
|
127
|
+
-----------------------------------oo-oo-oo-----------------o-ooooooo-o--------------o-o-----o-o----
|
128
|
+
-----------------------------------oooooooo-----------------o-o-----o-o-----------------oo-oo-------
|
129
|
+
-------------------------------------o--o----------------------oo-oo--------------------------------
|
130
|
+
------------------------------------o-oo-o----------------------------------------------------------
|
131
|
+
-----------------------------------o-o--o-o---------------------------------------------------------
|
132
|
+
----------------------------------------------------------------------------------------------------
|
133
|
+
----------------------------------------------------------------------------------------------------
|
134
|
+
----------------------------------------------------------------------------------------------------
|
135
|
+
----------------------------------------------------------------------------------------------------
|
136
|
+
----------------------------------------------------------------------------------------------------
|
137
|
+
-------------------oo-------------------------------------------------------------------------------
|
138
|
+
------------------oooo------------------------------------------------------------------------------
|
139
|
+
-----------------oooooo-----------------------------------------------------------------------------
|
140
|
+
----------------oo-oo-oo----------------------------------------------------------------------------
|
141
|
+
----------------oooooooo----------------------------------------------------------------------------
|
142
|
+
------------------o--o------------------------------------------------------------------------------
|
143
|
+
-----------------o-oo-o-----------------------------------------------------------------------------
|
144
|
+
----------------o-o--o-o----------------------------------------------------------------------------
|
145
|
+
----------------------------------------------------------------------------------------------------
|
146
|
+
----------------------------------------------------------------------------------------------------
|
147
|
+
----------------------------------------------------------------------------------------------------
|
148
|
+
----------------------------------------------------------------------------------------------------
|
149
|
+
----------------------------------------------------------------------------------------------------
|
150
|
+
-------------------------------------------------------------------------------------oo-------------
|
151
|
+
------------------------------------------------------------------------------------oooo------------
|
152
|
+
-----------------------------------------------------------------------------------oooooo-----------
|
153
|
+
----------------------------------------------------------------------------------oo-oo-oo----------
|
154
|
+
--------------------oo------------------------------------------------------------oooooooo----------
|
155
|
+
-------------------oooo-------------------------------------------------------------o--o------------
|
156
|
+
------------------oooooo-----------------------------------------------------------o-oo-o-----------
|
157
|
+
-----------------oo-oo-oo---------------------------------------------------------o-o--o-o----------
|
158
|
+
-----------------oooooooo---------------------------------------------------------------------------
|
159
|
+
~~~~
|
data/bin/xenos-enigma
ADDED
data/lib/xenos_enigma.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'xenos_enigma/runner'
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module XenosEnigma
|
2
|
+
module DefaultData
|
3
|
+
SCAN_DATA = <<~DATA.freeze
|
4
|
+
----o--oo----o--ooo--ooo--o------o---oo-o----oo---o--o---------o----o------o-------------o--o--o--o-
|
5
|
+
--o-o-----oooooooo-oooooo---o---o----o------ooo-o---o--o----o------o--o---ooo-----o--oo-o------o----
|
6
|
+
--o--------oo-ooo-oo-oo-oo-----O------------ooooo-----oo----o------o---o--o--o-o-o------o----o-o-o--
|
7
|
+
-------o--oooooo--o-oo-o--o-o-----oo--o-o-oo--o-oo-oo-o--------o-----o------o-ooooo---o--o--o-------
|
8
|
+
------o---o-ooo-ooo----o-----oo-------o---oo-ooooo-o------o----o--------o-oo--ooo-oo-------------o-o
|
9
|
+
-o--o-----o-o---o-ooooo-o-------oo---o---------o-----o-oo-----------oo----ooooooo-ooo-oo------------
|
10
|
+
o-------------ooooo-o--o--o--o-------o--o-oo-oo-o-o-o----oo------------o--oooo--ooo-o----o-----o--o-
|
11
|
+
--o-------------------------oo---------oo-o-o--ooo----oo----o--o--o----o--o-o-----o-o------o-o------
|
12
|
+
-------------------o----------o------o--o------o--------o--------o--oo-o-----oo-oo---o--o---o-----oo
|
13
|
+
----------o----------o---o--------------o--o----o--o-o------------oo------o--o-o---o-----o----------
|
14
|
+
------o----o-o---o-----o-o---o-----oo-o--------o---------------------------------o-o-o--o-----------
|
15
|
+
---------------o-------o-----o-------o-------------------o-----o---------o-o-------------o-------oo-
|
16
|
+
-o--o-------------o-o-----o--o--o--oo-------------o----ooo----o-------------o----------oo----o---o-o
|
17
|
+
-o--o-------------o----oo------o--o-------o--o-----o-----o----o-----o--o----o--oo-----------o-------
|
18
|
+
-o-----oo-------o------o----o----------o--o----o-----o-----o-------o-----------o---o-o--oooooo-----o
|
19
|
+
-o--------o-----o-----o---------oo----oo---o-o---------o---o--oooo-oo--o-------o------oo--oo--o-----
|
20
|
+
------------o---------o---------o----oooo-------------oo-oo-----ooo-oo-----o-------o-oo-oooooooo---o
|
21
|
+
----------------------o------------oooooooo---o-----o-------o--oooooo-o------------o-o-ooooooo-o----
|
22
|
+
------------o------o---o---o-------oo-oo--o--o---------o--o-o-o-ooooo-o--------------oo-o----o-oo-o-
|
23
|
+
---o-o----------oo-------oo----o----oooooooo-------o----o-o-o-o-----o-o-----o----------ooo-oo--o---o
|
24
|
+
-o-o---------o-o---------------o--o--o--ooo---ooo-------o------oo-oo------------o--------o--o-o--o--
|
25
|
+
-------oo---------------------------o-oo----------o------o-o-------o-----o----o-----o-oo-o-----o---o
|
26
|
+
---o--------o-----o-------o-oo-----oo--oo-o----oo----------o--o---oo------oo----o-----o-------o-----
|
27
|
+
---o--ooo-o---------o-o----o------------o---------o----o--o-------o----o--------o----------------oo-
|
28
|
+
---o------o----------------o----o------o------o---oo-----------o-------------o----------oo---------o
|
29
|
+
--oo---------------o--o------o---o-----o--o-------------o------o-------o-----o-----o----o------o--o-
|
30
|
+
-o-------o----------o-o-o-------o-----o--o-o-----------o-oo-----------o------o---------o-----o-o----
|
31
|
+
----------o----o-------o----o--o------o------------o---o---------------oo----o-----ooo--------------
|
32
|
+
----o--------oo----o-o----o--o------ooo----o-oooo---o--o-oo--------o-oo-----o-o---o-o--o-----oo-----
|
33
|
+
------o--------o-ooooo----o---o--o-----o---------------o-o-------o-----o----------------------------
|
34
|
+
o-------oo----o--oooooo-o---o--o------oooo----------o-oo-------o---o----------o------oo-------------
|
35
|
+
-o---o----------o--oo-oo-o---o-----o-o-----------------------oo--o------o------o--------------------
|
36
|
+
-----oo-o-o-o---ooooooooo----o----o--------o--o---oo---o------------o----------o-o---o------o-o--oo-
|
37
|
+
------o------o---ooo-o---------------------------o--o---o---o----o--o-------o-----o------o----o----o
|
38
|
+
-------o----------ooo-o-----o----o---o--o-oo--o--o-o--o------o--o-oo---ooo------------------------o-
|
39
|
+
-o-------o------o-o--ooo--o---o---oo-----o----o-------------o----o-ooo-o------o--o-o------o-o-------
|
40
|
+
---oo--o---o-o---------o---o--------------o--o-----o-------o-----o--o---o-oo--------o----o----o-----
|
41
|
+
o------o----oo-o-----------oo--o---o--------o-o------o-------o-o------o-oo---------o-----oo---------
|
42
|
+
----o--o---o-o-----------o---o------------o-------o----o--o--o--o-o---------------o-----------------
|
43
|
+
-------oo--o-o-----o-----o----o-o--o----------------------o-------o------o----oo----ooo---------o---
|
44
|
+
o-----oo-------------------o--o-----o-----------o------o-------o----o-----------o----------------o--
|
45
|
+
--o---o-------o------------o--------------------o----o--o-------------oo---o---------oo--------o----
|
46
|
+
--o--------o---------o------------o------o-------o------------o-------o---o---------ooooo-----------
|
47
|
+
------o--------------o-o-o---------o---o-------o--o-----o-------o-o----------o-----oo-ooo----------o
|
48
|
+
--o---------------o----o--oo-------------o---------o-------------------oo---------oo-o-ooo----------
|
49
|
+
-o-----------o------ooo----o----------------ooo-----o--------o--o---o-----------o-o-oooooo--------oo
|
50
|
+
-o---o-------o---o-oooo-----o-------------------o----oo-----------------o--o--------o--o------o--o--
|
51
|
+
-------o---o------oooooo--o----ooo--o--------o-------o----------------------------oo-oo-o--o--------
|
52
|
+
o--oo------o-----oo--o-oo------------oo--o------o--o-------------oo----o------------oooo-o------oo--
|
53
|
+
-----o----------ooooooooo--------------oo--------------oo-----o-----o-o--o------o----------o----o---
|
54
|
+
DATA
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module XenosEnigma
|
2
|
+
# HitCollector will consume all ship hits, and cache their data and coordinates
|
3
|
+
class HitCollector
|
4
|
+
def initialize
|
5
|
+
@hit_matrix_cache = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def detection_data(position_x, position_y)
|
9
|
+
get_cache(position_x, position_y)
|
10
|
+
end
|
11
|
+
|
12
|
+
def already_detected?(position_x, position_y)
|
13
|
+
!get_cache(position_x, position_y).nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
def push(xeno_hit, scan_position_x, scan_position_y)
|
17
|
+
xeno_hit.radar_x_position = scan_position_x
|
18
|
+
xeno_hit.radar_y_position = scan_position_y
|
19
|
+
|
20
|
+
consume(xeno_hit)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def consume(xeno_hit)
|
26
|
+
xeno_data = xeno_hit.xeno_instance.xeno_signature
|
27
|
+
|
28
|
+
xeno_data.each_with_index do |xeno_row_data, xeno_y|
|
29
|
+
next if xeno_y < xeno_hit.xeno_y_start
|
30
|
+
|
31
|
+
xeno_row = xeno_row_data.split(//)
|
32
|
+
xeno_row.each_with_index do |xeno_char, xeno_x|
|
33
|
+
global_x = xeno_hit.radar_x_position + xeno_x
|
34
|
+
global_y = xeno_hit.radar_y_position + xeno_y - xeno_hit.xeno_y_start
|
35
|
+
|
36
|
+
@hit_matrix_cache[cache_key(global_x, global_y)] = xeno_char
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_cache(position_x, position_y)
|
42
|
+
@hit_matrix_cache[cache_key(position_x, position_y)]
|
43
|
+
end
|
44
|
+
|
45
|
+
def cache_key(position_x, position_y)
|
46
|
+
"#{position_x}::#{position_y}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Hit is placeholder for ship detection information
|
51
|
+
class Hit
|
52
|
+
attr_accessor :radar_x_position,
|
53
|
+
:radar_y_position,
|
54
|
+
:xeno_instance,
|
55
|
+
:xeno_y_start
|
56
|
+
|
57
|
+
def initialize(xeno_instance, xeno_y_start = 0)
|
58
|
+
@xeno_instance = xeno_instance
|
59
|
+
@xeno_y_start = xeno_y_start
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require_relative 'default_data'
|
2
|
+
require_relative 'hit_collector'
|
3
|
+
Dir[File.expand_path('xenos/*.rb', File.dirname(__FILE__))].each do |file|
|
4
|
+
require_relative file
|
5
|
+
end
|
6
|
+
|
7
|
+
module XenosEnigma
|
8
|
+
# Radar will orchestrate scan of radar data, xenos detection and echo of those findings
|
9
|
+
class Radar
|
10
|
+
include DefaultData
|
11
|
+
|
12
|
+
def initialize(data = nil)
|
13
|
+
@data = (data || SCAN_DATA).split(/\n/)
|
14
|
+
@known_xenos = load_all_known_xenos
|
15
|
+
@hit_collector = XenosEnigma::HitCollector.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def scan
|
19
|
+
@data.each_with_index do |scan_row, scan_position_y|
|
20
|
+
(0..scan_row.length).each do |scan_position_x|
|
21
|
+
next if @hit_collector.already_detected?(scan_position_x, scan_position_y)
|
22
|
+
|
23
|
+
@known_xenos.each do |xeno|
|
24
|
+
partial = scan_row_partial(scan_row, scan_position_x, xeno.ship_width)
|
25
|
+
hit = xeno.analyze?(partial, look_ahead_data(scan_position_x, scan_position_y, xeno))
|
26
|
+
@hit_collector.push(hit, scan_position_x, scan_position_y) if hit
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def echo
|
33
|
+
echo_width = @data.first.size - 1
|
34
|
+
echo_height = @data.size - 1
|
35
|
+
print "\033[33m"
|
36
|
+
|
37
|
+
(0..echo_height).each do |echo_y|
|
38
|
+
(0..echo_width).each do |echo_x|
|
39
|
+
hit_data = @hit_collector.detection_data(echo_x, echo_y)
|
40
|
+
print hit_data || '-'
|
41
|
+
end
|
42
|
+
puts
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def look_ahead_data(position_x, position_y, xeno)
|
49
|
+
results = []
|
50
|
+
scan_to_y = [(position_y + xeno.ship_height), @data.size].min - 1
|
51
|
+
(position_y..scan_to_y).each do |scan_y|
|
52
|
+
partial = scan_row_partial(@data[scan_y], position_x, xeno.ship_width)
|
53
|
+
results.push(partial)
|
54
|
+
end
|
55
|
+
results
|
56
|
+
end
|
57
|
+
|
58
|
+
def scan_row_partial(scan_row, position_x, x_offset)
|
59
|
+
scan_row[position_x..(position_x + x_offset - 1)]
|
60
|
+
end
|
61
|
+
|
62
|
+
def load_all_known_xenos
|
63
|
+
xenox_clazzes = XenosEnigma::Xenos.constants.reject { |xc| xc.downcase.eql?(:base) }
|
64
|
+
xenox_clazzes.collect { |xc| XenosEnigma::Xenos.const_get(xc).new }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'radar'
|
2
|
+
require 'getoptlong'
|
3
|
+
|
4
|
+
module XenosEnigma
|
5
|
+
# Runner is responsable for end user interaction via console
|
6
|
+
class Runner
|
7
|
+
def self.start
|
8
|
+
radar_data = nil
|
9
|
+
|
10
|
+
opts = GetoptLong.new(['--help', '-h', GetoptLong::NO_ARGUMENT], ['--path', GetoptLong::OPTIONAL_ARGUMENT])
|
11
|
+
opts = Hash[*opts.get_option]
|
12
|
+
|
13
|
+
if opts['--help']
|
14
|
+
puts 'Usage: bin/run [--path FILE]'
|
15
|
+
puts "--help \t show help"
|
16
|
+
puts "--path FILE \t set path to radar data file, uses default data if no file provided"
|
17
|
+
exit(0)
|
18
|
+
end
|
19
|
+
|
20
|
+
if (file_provided = opts['--path'])
|
21
|
+
unless File.exist?(file_provided)
|
22
|
+
warn "File #{file_provided} not found"
|
23
|
+
exit(1)
|
24
|
+
end
|
25
|
+
|
26
|
+
radar_data = File.read(file_provided)
|
27
|
+
end
|
28
|
+
|
29
|
+
radar = XenosEnigma::Radar.new(radar_data)
|
30
|
+
radar.scan
|
31
|
+
radar.echo
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
module XenosEnigma
|
4
|
+
module Xenos
|
5
|
+
class Aeldari < Base
|
6
|
+
SIGNATURE = <<~SIGNATURE.freeze
|
7
|
+
--o-----o--
|
8
|
+
---o---o---
|
9
|
+
--ooooooo--
|
10
|
+
-oo-ooo-oo-
|
11
|
+
ooooooooooo
|
12
|
+
o-ooooooo-o
|
13
|
+
o-o-----o-o
|
14
|
+
---oo-oo---
|
15
|
+
SIGNATURE
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module XenosEnigma
|
2
|
+
module Xenos
|
3
|
+
# Base class holds all the logic for correctly detecting xenos ships
|
4
|
+
class Base
|
5
|
+
attr_reader :ship_width, :ship_height, :xeno_signature
|
6
|
+
|
7
|
+
SHIP_DETECTION = { tolerance: 2, compound_tolerance: 1.6, min_segments: 3 }.freeze
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
raise 'This is an abstract class' if instance_of?(XenosEnigma::Xenos::Base)
|
11
|
+
|
12
|
+
@xeno_signature = self.class::SIGNATURE.split(/\n/)
|
13
|
+
@ship_width = @xeno_signature.first.size
|
14
|
+
@ship_height = @xeno_signature.size
|
15
|
+
end
|
16
|
+
|
17
|
+
def analyze?(radar_partial, look_ahead_radar_data)
|
18
|
+
return if radar_partial.size < ship_width
|
19
|
+
|
20
|
+
hit = nil
|
21
|
+
|
22
|
+
@xeno_signature.each_with_index do |xeno_row, xeno_y_position|
|
23
|
+
if possible_match?(xeno_row, radar_partial)
|
24
|
+
hit = full_scan(xeno_y_position, look_ahead_radar_data)
|
25
|
+
break if hit
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
hit
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def full_scan(xeno_y_position, look_ahead_radar_data)
|
35
|
+
compound_match_score = 0
|
36
|
+
lines_scanned = 0
|
37
|
+
|
38
|
+
(xeno_y_position..(ship_height - 1)).each do |y_scan|
|
39
|
+
break if look_ahead_radar_data[y_scan - xeno_y_position].nil?
|
40
|
+
|
41
|
+
compound_match_score += pattern_difference(@xeno_signature[y_scan], look_ahead_radar_data[y_scan - xeno_y_position])
|
42
|
+
lines_scanned += 1
|
43
|
+
end
|
44
|
+
|
45
|
+
is_detection_cofirmed = (lines_scanned * SHIP_DETECTION[:compound_tolerance] >= compound_match_score)
|
46
|
+
|
47
|
+
if lines_scanned >= SHIP_DETECTION[:min_segments] && is_detection_cofirmed
|
48
|
+
XenosEnigma::Hit.new(self, xeno_y_position)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def possible_match?(xeno_row, radar_partial)
|
53
|
+
pattern_difference(xeno_row, radar_partial) <= SHIP_DETECTION[:tolerance]
|
54
|
+
end
|
55
|
+
|
56
|
+
def pattern_difference(data1, data2)
|
57
|
+
DidYouMean::Levenshtein.distance(data1, data2)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative '../lib/xenos_enigma/xenos/tau'
|
2
|
+
require_relative 'helpers/randomize'
|
3
|
+
|
4
|
+
RSpec.configure do |config|
|
5
|
+
config.include Randomize
|
6
|
+
end
|
7
|
+
|
8
|
+
RSpec.describe XenosEnigma::Xenos::Base do
|
9
|
+
describe 'instance methods' do
|
10
|
+
let(:tau) { XenosEnigma::Xenos::Tau.new }
|
11
|
+
let(:data) { tau.xeno_signature }
|
12
|
+
|
13
|
+
it 'should not allow class to be instanced' do
|
14
|
+
expect { XenosEnigma::Xenos::Base.new }.to raise_exception(RuntimeError, 'This is an abstract class')
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should match pattern as a possible match' do
|
18
|
+
expect(tau.send(:possible_match?, '---oo---', '---o-o--')).to be true
|
19
|
+
expect(tau.send(:possible_match?, '---oo---', '--o-o---')).to be true
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should not match pattern as a possible match' do
|
23
|
+
expect(tau.send(:possible_match?, '---oo---', '-----o--')).to be false
|
24
|
+
expect(tau.send(:possible_match?, '---oo---', '--o-----')).to be false
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should analyze data correctly and return exact hit' do
|
28
|
+
rdata = randomize_data(data)
|
29
|
+
result = tau.analyze?(rdata[0], rdata)
|
30
|
+
|
31
|
+
expect(result).to be_a XenosEnigma::Hit
|
32
|
+
expect(result.xeno_y_start).to eq 0
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should analyze data correctly and return partial hit from top of the ship' do
|
36
|
+
rdata = randomize_data(data.take(5))
|
37
|
+
result = tau.analyze?(rdata[0], rdata)
|
38
|
+
|
39
|
+
expect(result).to be_a XenosEnigma::Hit
|
40
|
+
expect(result.xeno_y_start).to eq 0
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should analyze data correctly and return partial hit from bottom of the ship' do
|
44
|
+
ship_segments = 4
|
45
|
+
|
46
|
+
partial_data = data.dup[ship_segments..-1]
|
47
|
+
rdata = randomize_data(partial_data)
|
48
|
+
result = tau.analyze?(rdata[0], rdata)
|
49
|
+
|
50
|
+
expect(result).to be_a XenosEnigma::Hit
|
51
|
+
expect(result.xeno_y_start).to eq ship_segments
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should analyze data and not return a hit' do
|
55
|
+
rdata = randomize_data(['--------'] * 8)
|
56
|
+
result = tau.analyze?(rdata[0], rdata)
|
57
|
+
|
58
|
+
expect(result).to be_falsey
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative '../lib/xenos_enigma/hit_collector'
|
2
|
+
require_relative '../lib/xenos_enigma/xenos/aeldari'
|
3
|
+
|
4
|
+
RSpec.describe XenosEnigma::HitCollector do
|
5
|
+
describe 'instance methods' do
|
6
|
+
subject { XenosEnigma::HitCollector.new }
|
7
|
+
let(:aeldari) { XenosEnigma::Xenos::Aeldari.new }
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
@hit = XenosEnigma::Hit.new(aeldari)
|
11
|
+
subject.push(@hit, 0, 0)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should correctly process a new hit and each coordinate' do
|
15
|
+
(0..aeldari.ship_width - 1).each do |position_x|
|
16
|
+
(0..aeldari.ship_height - 1).each do |position_y|
|
17
|
+
expect(subject.already_detected?(position_x, position_y)).to be true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should correctly process a new hit and mark each ship segment' do
|
23
|
+
scanned_data = []
|
24
|
+
(0..aeldari.ship_width - 1).each do |position_x|
|
25
|
+
(0..aeldari.ship_height - 1).each do |position_y|
|
26
|
+
scanned_data << subject.detection_data(position_x, position_y)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
ship_signiture = @hit.xeno_instance.xeno_signature.collect do |row|
|
31
|
+
row.split(//)
|
32
|
+
end.flatten.sort
|
33
|
+
|
34
|
+
expect(ship_signiture).to eq scanned_data.sort
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/spec/radar_spec.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require_relative '../lib/xenos_enigma/radar'
|
2
|
+
|
3
|
+
RSpec.describe XenosEnigma::Radar do
|
4
|
+
describe 'when working with default data' do
|
5
|
+
subject { XenosEnigma::Radar.new }
|
6
|
+
let(:tau) { XenosEnigma::Xenos::Tau.new }
|
7
|
+
let(:expected_data) do
|
8
|
+
<<~DATA.freeze
|
9
|
+
----o--o
|
10
|
+
--o-o---
|
11
|
+
--o-----
|
12
|
+
-------o
|
13
|
+
------o-
|
14
|
+
-o--o---
|
15
|
+
o-------
|
16
|
+
--o-----
|
17
|
+
DATA
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'collect all known xenos' do
|
21
|
+
xenos = subject.instance_variable_get(:@known_xenos)
|
22
|
+
|
23
|
+
expect(xenos).to be_a Array
|
24
|
+
expect(xenos).not_to be_empty
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'make sure that each xenos is analyzed' do
|
28
|
+
expect_any_instance_of(XenosEnigma::Xenos::Tau).to receive(:analyze?).at_least(:once)
|
29
|
+
expect_any_instance_of(XenosEnigma::Xenos::Aeldari).to receive(:analyze?).at_least(:once)
|
30
|
+
|
31
|
+
subject.scan
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns correct scan ahead data' do
|
35
|
+
data = subject.send(:look_ahead_data, 0, 0, tau)
|
36
|
+
|
37
|
+
expect(data).to eq expected_data.split(/\n/)
|
38
|
+
expect(data.first.size).to eq(tau.ship_width)
|
39
|
+
expect(data.size).to eq(tau.ship_height)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns correct data partial' do
|
43
|
+
data = subject.send(:scan_row_partial, expected_data, 0, 5)
|
44
|
+
expect(data).to eq '----o'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: xenos-enigma
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Haris Krajina
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-07-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.1.0
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.1.0
|
27
|
+
description:
|
28
|
+
email:
|
29
|
+
- haris.krajina@gmail.com
|
30
|
+
executables:
|
31
|
+
- xenos-enigma
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files:
|
34
|
+
- CHANGELOG
|
35
|
+
- LICENSE
|
36
|
+
- README.md
|
37
|
+
files:
|
38
|
+
- CHANGELOG
|
39
|
+
- LICENSE
|
40
|
+
- README.md
|
41
|
+
- bin/xenos-enigma
|
42
|
+
- lib/xenos_enigma.rb
|
43
|
+
- lib/xenos_enigma/default_data.rb
|
44
|
+
- lib/xenos_enigma/hit_collector.rb
|
45
|
+
- lib/xenos_enigma/radar.rb
|
46
|
+
- lib/xenos_enigma/runner.rb
|
47
|
+
- lib/xenos_enigma/version.rb
|
48
|
+
- lib/xenos_enigma/xenos/aeldari.rb
|
49
|
+
- lib/xenos_enigma/xenos/base.rb
|
50
|
+
- lib/xenos_enigma/xenos/tau.rb
|
51
|
+
- spec/base_spec.rb
|
52
|
+
- spec/helpers/randomize.rb
|
53
|
+
- spec/hit_collector_spec.rb
|
54
|
+
- spec/radar_spec.rb
|
55
|
+
homepage: http://github.com/hkraji/xenos-enigma
|
56
|
+
licenses:
|
57
|
+
- MIT
|
58
|
+
metadata: {}
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '2.4'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubygems_version: 3.1.2
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: Space invaders radar set in the world of 40k
|
78
|
+
test_files:
|
79
|
+
- spec/hit_collector_spec.rb
|
80
|
+
- spec/radar_spec.rb
|
81
|
+
- spec/helpers/randomize.rb
|
82
|
+
- spec/base_spec.rb
|