tenpai_wakaru_man 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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/README.md +32 -0
- data/Rakefile +6 -0
- data/benchmark.rb +10 -0
- data/bin/console +10 -0
- data/bin/setup +8 -0
- data/lib/tenpai_wakaru_man/calculator.rb +34 -0
- data/lib/tenpai_wakaru_man/errors.rb +3 -0
- data/lib/tenpai_wakaru_man/fu_counter.rb +64 -0
- data/lib/tenpai_wakaru_man/hand.rb +164 -0
- data/lib/tenpai_wakaru_man/meld.rb +93 -0
- data/lib/tenpai_wakaru_man/parser.rb +36 -0
- data/lib/tenpai_wakaru_man/ten.rb +5 -0
- data/lib/tenpai_wakaru_man/ten.yml +30 -0
- data/lib/tenpai_wakaru_man/tiles.rb +9 -0
- data/lib/tenpai_wakaru_man/version.rb +3 -0
- data/lib/tenpai_wakaru_man.rb +29 -0
- data/stackprof.rb +9 -0
- data/tenpai_wakaru_man.gemspec +27 -0
- metadata +148 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b743170bdc05f43954be6f9a5812e3df3f20024b
|
4
|
+
data.tar.gz: b6937aea8c54e68a5005037b84b6f2aa4f526051
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fa943324ec7da63a27f9a3e61be038c16599b88c21ebe45c3694320b61d44ac0996a89776bc0e34e535167421a202abd1f86f7021b3164335f23d79f1b7eade6
|
7
|
+
data.tar.gz: e20af9aceae4f7941c1a411915f402708e35c342b7996ec174b27c8a33dcebf7a120cc3f72a944fdbfdc5f6f51fc93f46165e7ace7cacb315d1ab6ed0b9c280a
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# TenpaiWakaruMan
|
2
|
+
[](https://travis-ci.org/flada-auxv/tenpai_wakaru_man)
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
gem 'tenpai_wakaru_man'
|
10
|
+
```
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install tenpai_wakaru_man
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
TODO: Write usage instructions here
|
23
|
+
|
24
|
+
## Development
|
25
|
+
|
26
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
27
|
+
|
28
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
29
|
+
|
30
|
+
## Contributing
|
31
|
+
|
32
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[flada-auxv]/tenpai_wakaru_man.
|
data/Rakefile
ADDED
data/benchmark.rb
ADDED
data/bin/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "tenpai_wakaru_man"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
require "pry"
|
10
|
+
Pry.start
|
data/bin/setup
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'tenpai_wakaru_man/ten'
|
2
|
+
require 'tenpai_wakaru_man/fu_counter'
|
3
|
+
|
4
|
+
module TenpaiWakaruMan
|
5
|
+
class Calculator
|
6
|
+
class << self
|
7
|
+
def calculate(tiles)
|
8
|
+
new.calculate(tiles)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
end
|
14
|
+
|
15
|
+
def calculate(tiles, options = {})
|
16
|
+
return nil if (hands = Parser.parse(tiles).winning_hands).empty?
|
17
|
+
|
18
|
+
hands.map {|hand|
|
19
|
+
options[:tsumo_or_ron] = :ron
|
20
|
+
|
21
|
+
fu = FuCounter.count(hand)
|
22
|
+
han = HanCounter.count(hand)
|
23
|
+
|
24
|
+
{fu: fu, han: han, ten: TEN[han.size][fu][options[:tsumo_or_ron].to_s]}
|
25
|
+
}.max {|hash| hash[:ten] }
|
26
|
+
end
|
27
|
+
|
28
|
+
class HanCounter
|
29
|
+
def self.count(hand)
|
30
|
+
%i(pinfu)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module TenpaiWakaruMan
|
2
|
+
class FuCounter
|
3
|
+
HUTEI = 20
|
4
|
+
MENZEN_KAFU = 10
|
5
|
+
MELDS = {
|
6
|
+
pair: 0,
|
7
|
+
run: 0,
|
8
|
+
open_triplet: 2,
|
9
|
+
closed_triplet: 4,
|
10
|
+
open_quad: 8,
|
11
|
+
closed_quad: 16
|
12
|
+
}
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def count(hand, options)
|
16
|
+
new(hand).count(options)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(hand)
|
21
|
+
@hand = hand
|
22
|
+
end
|
23
|
+
|
24
|
+
# tsumo_or_ron: [:tsumo, :ron]
|
25
|
+
# prevailing_wind: ["Ew", "Sw", "Ww", "Nw"]
|
26
|
+
# seat_wind: ["Ew", "Sw", "Ww", "Nw"]
|
27
|
+
# waits: [:ryanmen, :kanchan, :penchan, :tanki, :shanpon]
|
28
|
+
def count(options = {})
|
29
|
+
fu = HUTEI +
|
30
|
+
count_by_win_kind(options[:tsumo_or_ron]) +
|
31
|
+
count_by_melds +
|
32
|
+
count_by_head(prevailing_wind: options[:prevailing_wind], seat_wind: options[:seat_wind]) +
|
33
|
+
count_by_waits(options[:waits])
|
34
|
+
|
35
|
+
(fu / 10.0).ceil * 10
|
36
|
+
end
|
37
|
+
|
38
|
+
def count_by_win_kind(tsumo_or_ron)
|
39
|
+
fu = 0
|
40
|
+
fu += MENZEN_KAFU if tsumo_or_ron == :ron && @hand.closed?
|
41
|
+
fu += 2 if tsumo_or_ron == :tsumo
|
42
|
+
fu
|
43
|
+
end
|
44
|
+
|
45
|
+
def count_by_melds
|
46
|
+
@hand.melds.map {|meld|
|
47
|
+
fu = MELDS[meld.type]
|
48
|
+
fu *= 2 if meld.include_terminal_or_honor?
|
49
|
+
fu
|
50
|
+
}.inject(&:+)
|
51
|
+
end
|
52
|
+
|
53
|
+
def count_by_head(prevailing_wind:, seat_wind:)
|
54
|
+
fu = 0
|
55
|
+
fu += 2 if @hand.head == prevailing_wind
|
56
|
+
fu += 2 if @hand.head == seat_wind
|
57
|
+
fu
|
58
|
+
end
|
59
|
+
|
60
|
+
def count_by_waits(waits)
|
61
|
+
%i(kanchan penchan tanki).include?(waits) ? 2 : 0
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'tenpai_wakaru_man/errors'
|
2
|
+
|
3
|
+
module TenpaiWakaruMan
|
4
|
+
class Hand
|
5
|
+
attr_accessor :head, :tiles, :melds
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def build(head: nil, tiles: [], melds: [])
|
9
|
+
new(head: head, tiles: tiles, melds: melds)
|
10
|
+
rescue TileCountError
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse_from(tile_str)
|
15
|
+
Parser.parse(tile_str)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(head: nil, tiles: [], melds: [])
|
20
|
+
@head = head
|
21
|
+
@tiles = tiles.sort_by {|tile| TILES[tile] }
|
22
|
+
@melds = melds.sort
|
23
|
+
|
24
|
+
check_tile_count!
|
25
|
+
end
|
26
|
+
|
27
|
+
def ==(other)
|
28
|
+
head == other.head && tiles == other.tiles && melds == other.melds
|
29
|
+
end
|
30
|
+
|
31
|
+
def dup
|
32
|
+
self.class.new(head: head&.dup, tiles: tiles.dup, melds: melds.dup)
|
33
|
+
end
|
34
|
+
|
35
|
+
def inspect
|
36
|
+
"#<#{self.class.name}:\"#{to_msp_notation}\", @head=#{@head.inspect}, @melds=#{@melds.map(&:to_s)}, @tiles=#{@tiles}>"
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_msp_notation
|
40
|
+
([Meld.new(@tiles)] + @melds).sort.map(&:msp_notation).join
|
41
|
+
end
|
42
|
+
alias :to_s :to_msp_notation
|
43
|
+
|
44
|
+
def winning?
|
45
|
+
!winning_hands.empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
def winning_hands
|
49
|
+
detect_special_form!
|
50
|
+
|
51
|
+
@winning_hands ||= head_candidates.map {|head| dup.set_head(head) }.map {|hand| hand.detect_winning_hands }.reject(&:empty?).flatten
|
52
|
+
end
|
53
|
+
|
54
|
+
def detect_winning_hands
|
55
|
+
meld_combination.map {|melds| self.class.build(head: @head.dup, melds: melds) }.compact.select {|hand| hand.all_tiles == all_tiles }
|
56
|
+
end
|
57
|
+
|
58
|
+
def ready?
|
59
|
+
TILES.each_key.any? {|tile|
|
60
|
+
hand = dup
|
61
|
+
hand.tiles << tile
|
62
|
+
hand.winning?
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
def set_head(tile)
|
67
|
+
self.head = tile
|
68
|
+
@tiles.slice!(@tiles.index(tile), 2)
|
69
|
+
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
def closed?
|
74
|
+
melds.all?(&:closed?)
|
75
|
+
end
|
76
|
+
|
77
|
+
def open?
|
78
|
+
!closed?
|
79
|
+
end
|
80
|
+
|
81
|
+
def all_tiles
|
82
|
+
(tiles + melds.map(&:tiles)).flatten.sort_by {|tile| TILES[tile] }
|
83
|
+
end
|
84
|
+
|
85
|
+
def seven_pairs?
|
86
|
+
count_by.keys.count == 7 && count_by.values.all? {|i| i == 2 }
|
87
|
+
end
|
88
|
+
|
89
|
+
def thirteen_orphans?
|
90
|
+
count_by.keys.count == 13 && all_tiles.all? {|tile| tile[/[#{Parser::HONOR_SYMBOLS}]/] || tile[/[19]/] }
|
91
|
+
end
|
92
|
+
|
93
|
+
def meld_combination
|
94
|
+
each_with_rest((@melds + meld_candidates)).with_object([]) {|(meld, rest_candidates), result|
|
95
|
+
rest_tiles = extract_meld(all_tiles, meld)
|
96
|
+
result.push(*_combination(rest_candidates, Array(meld), rest_tiles))
|
97
|
+
}.uniq {|meld_arr| meld_arr.map(&:tiles).hash }
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def _combination(candidates, current_result, tiles, result = [])
|
103
|
+
return [] if (candidates.count + current_result.count) < 4
|
104
|
+
|
105
|
+
each_with_rest(candidates).with_object(result) {|(meld, rest_candidates), result|
|
106
|
+
next unless rest_tiles = extract_meld(tiles, meld)
|
107
|
+
|
108
|
+
_current_result = current_result.dup << meld
|
109
|
+
|
110
|
+
if _current_result.count == 4
|
111
|
+
result << _current_result
|
112
|
+
else
|
113
|
+
_combination(rest_candidates, _current_result, rest_tiles, result)
|
114
|
+
end
|
115
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
def each_with_rest(array)
|
119
|
+
if block_given?
|
120
|
+
array.each_with_index {|elem, i| yield elem, array[i+1..-1] }
|
121
|
+
else
|
122
|
+
array.map.with_index {|elem, i| [elem, array[i+1..-1]] }.each
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def extract_meld(tiles, meld)
|
127
|
+
copied = tiles.dup
|
128
|
+
|
129
|
+
deleted = meld.tiles.map {|tile|
|
130
|
+
(index = copied.find_index(tile)) ? copied.delete_at(index) : nil
|
131
|
+
}
|
132
|
+
|
133
|
+
deleted.compact.count == meld.tiles.count ? copied : nil
|
134
|
+
end
|
135
|
+
|
136
|
+
def head_candidates
|
137
|
+
@tiles.uniq.select {|t| @tiles.count(t) >= 2 }
|
138
|
+
end
|
139
|
+
|
140
|
+
def meld_candidates
|
141
|
+
(triplet_candidates + run_candidates).sort
|
142
|
+
end
|
143
|
+
|
144
|
+
def triplet_candidates
|
145
|
+
count_by.select {|tile, count| count >= 3 }.keys.map {|t| Meld.new([t, t, t]) }
|
146
|
+
end
|
147
|
+
|
148
|
+
def run_candidates
|
149
|
+
@tiles.combination(3).map {|tiles| Meld.new(tiles) }.select {|meld| meld.run? }
|
150
|
+
end
|
151
|
+
|
152
|
+
def count_by
|
153
|
+
all_tiles.group_by {|tile| tile }.each_with_object({}) {|(k,v), hash| hash[k] = v.count }
|
154
|
+
end
|
155
|
+
|
156
|
+
def detect_special_form!
|
157
|
+
@winning_hands = Array(dup) if thirteen_orphans? || seven_pairs?
|
158
|
+
end
|
159
|
+
|
160
|
+
def check_tile_count!
|
161
|
+
raise TileCountError.new('some tiles existing than four.') if count_by.any? {|key, count| count > 4 }
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "tenpai_wakaru_man/tiles"
|
2
|
+
require "tenpai_wakaru_man/parser"
|
3
|
+
|
4
|
+
module TenpaiWakaruMan
|
5
|
+
class Meld
|
6
|
+
attr_accessor :tiles, :msp_notation
|
7
|
+
|
8
|
+
def initialize(tiles)
|
9
|
+
case tiles
|
10
|
+
when String
|
11
|
+
@msp_notation = tiles
|
12
|
+
@tiles = Parser.split(@msp_notation)
|
13
|
+
when Array
|
14
|
+
@tiles = tiles.sort_by {|tile| TILES[tile] }
|
15
|
+
@msp_notation = to_msp_notation
|
16
|
+
end
|
17
|
+
|
18
|
+
@unique_count = @tiles.uniq.count
|
19
|
+
@count = @tiles.count
|
20
|
+
end
|
21
|
+
|
22
|
+
def ==(other)
|
23
|
+
@msp_notation == other.msp_notation
|
24
|
+
end
|
25
|
+
|
26
|
+
def <=>(other)
|
27
|
+
msp_notation <=> other.msp_notation
|
28
|
+
end
|
29
|
+
|
30
|
+
def inspect
|
31
|
+
"#<#{self.class.name}:\"#{@msp_notation}\">"
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_s
|
35
|
+
@msp_notation
|
36
|
+
end
|
37
|
+
|
38
|
+
def open?; !!@msp_notation[/[#{Parser::OPEN_MELDED_SYMBOLS}]/] end
|
39
|
+
def closed?; !open? end
|
40
|
+
def revealed?; @revealed ||= open? || closed_quad? end
|
41
|
+
|
42
|
+
def pair?; @unique_count == 1 && @count == 2 end
|
43
|
+
def triplet?; @unique_count == 1 && @count == 3 end
|
44
|
+
def quad?; @unique_count == 1 && @count == 4 end
|
45
|
+
def run?
|
46
|
+
return false unless @tiles.map {|tile| tile[-1] }.uniq.count == 1
|
47
|
+
|
48
|
+
chow_candidates = @tiles.map {|tile| TILES[tile] }.select {|tile| tile > 6 }
|
49
|
+
|
50
|
+
return false unless chow_candidates.uniq.count == 3
|
51
|
+
|
52
|
+
[chow_candidates[0] + 2, chow_candidates[1] + 1, chow_candidates[2]].uniq.count == 1
|
53
|
+
end
|
54
|
+
|
55
|
+
def open_triplet?; open? && triplet? end
|
56
|
+
def closed_triplet?; closed? && triplet? end
|
57
|
+
def open_quad?; open? && quad? end
|
58
|
+
def closed_quad?; closed? && quad? end
|
59
|
+
|
60
|
+
def type
|
61
|
+
case
|
62
|
+
when pair?; :pair
|
63
|
+
when run?; :run
|
64
|
+
when open_triplet?; :open_triplet
|
65
|
+
when closed_triplet?; :closed_triplet
|
66
|
+
when open_quad?; :open_quad
|
67
|
+
when closed_quad?; :closed_quad
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def include_honor?
|
72
|
+
!!@msp_notation[/[#{Parser::HONOR_SYMBOLS}]/]
|
73
|
+
end
|
74
|
+
|
75
|
+
def include_terminal?
|
76
|
+
!!@msp_notation[/[19]/]
|
77
|
+
end
|
78
|
+
|
79
|
+
def include_terminal_or_honor?
|
80
|
+
include_honor? || include_terminal?
|
81
|
+
end
|
82
|
+
|
83
|
+
def exclude_terminal_or_honor?
|
84
|
+
!include_terminal_or_honor?
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def to_msp_notation
|
90
|
+
@tiles.sort_by {|tile| TILES[tile] }.map {|tile| tile.split("") }.chunk {|_, suite| suite }.map {|key, arr| arr.map(&:first).join << key }.join
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'tenpai_wakaru_man/hand'
|
2
|
+
require 'tenpai_wakaru_man/meld'
|
3
|
+
|
4
|
+
module TenpaiWakaruMan
|
5
|
+
class Parser
|
6
|
+
SUITED_SYMBOLS = "msp"
|
7
|
+
DRAGON_SYMBOL = "d"
|
8
|
+
WIND_SYMBOL = "w"
|
9
|
+
OPEN_MELDED_SYMBOLS = "lar"
|
10
|
+
HONOR_SYMBOLS = DRAGON_SYMBOL + WIND_SYMBOL
|
11
|
+
MELD_SYMBOLS = SUITED_SYMBOLS + HONOR_SYMBOLS + OPEN_MELDED_SYMBOLS
|
12
|
+
|
13
|
+
MELD_REGEXP = /((\d+[#{SUITED_SYMBOLS}]|[PFC]+#{DRAGON_SYMBOL}|[ESWN]+#{WIND_SYMBOL})[#{OPEN_MELDED_SYMBOLS}]?)/
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def scan(tile_str)
|
17
|
+
tile_str.scan(MELD_REGEXP).map {|tile_with_suite, _| tile_with_suite }
|
18
|
+
end
|
19
|
+
|
20
|
+
def split(tile_str)
|
21
|
+
scan(tile_str).map {|tile|
|
22
|
+
meld_type = tile[/[#{MELD_SYMBOLS}]/]
|
23
|
+
tile.delete(MELD_SYMBOLS).chars.map {|str| str + meld_type }
|
24
|
+
}.flatten.sort_by {|tile| TILES[tile] }
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse(tile_str)
|
28
|
+
args = scan(tile_str).map {|tiles| Meld.new(tiles) }.chunk {|meld| meld.revealed? }.each_with_object({melds: [], tiles: []}) {|(bool, value), hash|
|
29
|
+
bool ? hash[:melds] += value : hash[:tiles] += value.map(&:tiles).flatten
|
30
|
+
}
|
31
|
+
|
32
|
+
Hand.build(args)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
1:
|
2
|
+
20:
|
3
|
+
tsumo: [400, 700]
|
4
|
+
30:
|
5
|
+
ron: 1000
|
6
|
+
tsumo: [300, 500]
|
7
|
+
40:
|
8
|
+
ron: 1300
|
9
|
+
tsumo: [400, 700]
|
10
|
+
50:
|
11
|
+
ron: 1600
|
12
|
+
tsumo: [400, 800]
|
13
|
+
60:
|
14
|
+
ron: 2000
|
15
|
+
tsumo: [500, 1000]
|
16
|
+
70:
|
17
|
+
ron: 2300
|
18
|
+
tsumo: [600, 1200]
|
19
|
+
80:
|
20
|
+
ron: 2600
|
21
|
+
tsumo: [700, 1300]
|
22
|
+
90:
|
23
|
+
ron: 2900
|
24
|
+
tsumo: [800, 1500]
|
25
|
+
100:
|
26
|
+
ron: 3200
|
27
|
+
tsumo: [800, 1600]
|
28
|
+
110:
|
29
|
+
ron: 3600
|
30
|
+
tsumo: [900, 1800]
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module TenpaiWakaruMan
|
2
|
+
TILES = {
|
3
|
+
"Ew" => 0, "Sw" => 1, "Ww" => 2, "Nw" => 3,
|
4
|
+
"Cd" => 4, "Fd" => 5, "Pd" => 6,
|
5
|
+
"1m" => 7, "2m" => 8, "3m" => 9, "4m" => 10, "5m" => 11, "6m" => 12, "7m" => 13, "8m" => 14, "9m" => 15,
|
6
|
+
"1s" => 16, "2s" => 17, "3s" => 18, "4s" => 19, "5s" => 20, "6s" => 21, "7s" => 22, "8s" => 23, "9s" => 24,
|
7
|
+
"1p" => 25, "2p" => 26, "3p" => 27, "4p" => 28, "5p" => 29, "6p" => 30, "7p" => 31, "8p" => 32, "9p" => 33
|
8
|
+
}.freeze
|
9
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "tenpai_wakaru_man/version"
|
2
|
+
require "tenpai_wakaru_man/errors"
|
3
|
+
require "tenpai_wakaru_man/parser"
|
4
|
+
require "tenpai_wakaru_man/calculator"
|
5
|
+
|
6
|
+
module TenpaiWakaruMan
|
7
|
+
class Detector
|
8
|
+
class << self
|
9
|
+
def winning?(str)
|
10
|
+
new.winning?(str)
|
11
|
+
end
|
12
|
+
|
13
|
+
def ready?(str)
|
14
|
+
new.ready?(str)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
end
|
20
|
+
|
21
|
+
def winning?(tiles)
|
22
|
+
Parser.parse(tiles).winning?
|
23
|
+
end
|
24
|
+
|
25
|
+
def ready?(tiles)
|
26
|
+
Parser.parse(tiles).ready?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/stackprof.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# bundle exec ruby stackprof.rb
|
2
|
+
# bundle exec stackprof tmp/stackprof-cpu-myapp.dump --text --limit 5
|
3
|
+
|
4
|
+
require 'stackprof'
|
5
|
+
require 'tenpai_wakaru_man'
|
6
|
+
|
7
|
+
StackProf.run(mode: :cpu, out: 'tmp/stackprof-cpu-myapp.dump') do
|
8
|
+
TenpaiWakaruMan::Detector.winning?("11122233445555m")
|
9
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'tenpai_wakaru_man/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "tenpai_wakaru_man"
|
8
|
+
spec.version = TenpaiWakaruMan::VERSION
|
9
|
+
spec.authors = ["flada-auxv"]
|
10
|
+
spec.email = ["aseknock@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{TenpaiWakaruMan}
|
13
|
+
spec.description = %q{TenpaiWakaruMan}
|
14
|
+
spec.homepage = "https://github.com/flada-auxv/tenpai_wakaru_man"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
24
|
+
spec.add_development_dependency "pry", "~> 0.10.0"
|
25
|
+
spec.add_development_dependency "stackprof"
|
26
|
+
spec.add_development_dependency "benchmark-ips"
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tenpai_wakaru_man
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- flada-auxv
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-08-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.11'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.11'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.10.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.10.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: stackprof
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: benchmark-ips
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: TenpaiWakaruMan
|
98
|
+
email:
|
99
|
+
- aseknock@gmail.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- ".travis.yml"
|
106
|
+
- Gemfile
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- benchmark.rb
|
110
|
+
- bin/console
|
111
|
+
- bin/setup
|
112
|
+
- lib/tenpai_wakaru_man.rb
|
113
|
+
- lib/tenpai_wakaru_man/calculator.rb
|
114
|
+
- lib/tenpai_wakaru_man/errors.rb
|
115
|
+
- lib/tenpai_wakaru_man/fu_counter.rb
|
116
|
+
- lib/tenpai_wakaru_man/hand.rb
|
117
|
+
- lib/tenpai_wakaru_man/meld.rb
|
118
|
+
- lib/tenpai_wakaru_man/parser.rb
|
119
|
+
- lib/tenpai_wakaru_man/ten.rb
|
120
|
+
- lib/tenpai_wakaru_man/ten.yml
|
121
|
+
- lib/tenpai_wakaru_man/tiles.rb
|
122
|
+
- lib/tenpai_wakaru_man/version.rb
|
123
|
+
- stackprof.rb
|
124
|
+
- tenpai_wakaru_man.gemspec
|
125
|
+
homepage: https://github.com/flada-auxv/tenpai_wakaru_man
|
126
|
+
licenses: []
|
127
|
+
metadata: {}
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
requirements: []
|
143
|
+
rubyforge_project:
|
144
|
+
rubygems_version: 2.5.1
|
145
|
+
signing_key:
|
146
|
+
specification_version: 4
|
147
|
+
summary: TenpaiWakaruMan
|
148
|
+
test_files: []
|