Class: Mjai::JSONizable

Inherits:
Object
  • Object
show all
Defined in:
lib/mjai/jsonizable.rb

Direct Known Subclasses

Action

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fields) ⇒ JSONizable

Returns a new instance of JSONizable.



119
120
121
122
123
124
125
126
# File 'lib/mjai/jsonizable.rb', line 119

def initialize(fields)
  for name, value in fields
    if !@@field_specs.any?(){ |n, t| n == name }
      raise(ArgumentError, "unknown field: %p" % name)
    end
  end
  @fields = fields
end

Instance Attribute Details

#fieldsObject (readonly)

Returns the value of attribute fields.



128
129
130
# File 'lib/mjai/jsonizable.rb', line 128

def fields
  @fields
end

Class Method Details

.define_fields(specs) ⇒ Object



11
12
13
14
15
16
17
18
# File 'lib/mjai/jsonizable.rb', line 11

def self.define_fields(specs)
  @@field_specs = specs
  @@field_specs.each() do |name, type|
    define_method(name) do
      return @fields[name]
    end
  end
end

.from_json(json, game) ⇒ Object



20
21
22
23
24
25
26
27
# File 'lib/mjai/jsonizable.rb', line 20

def self.from_json(json, game)
  plain = JSON.parse(json)
  begin
    return from_plain(plain, nil, game)
  rescue ValidationError => ex
    raise(ValidationError, "%s JSON: %s" % [ex.message, json])
  end
end

.from_plain(plain, name, game) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
# File 'lib/mjai/jsonizable.rb', line 29

def self.from_plain(plain, name, game)
  validate(plain.is_a?(Hash), "%s must be an object." % (name || "The response"))
  fields = {}
  for field_name, type in @@field_specs
    field_plain = plain[field_name.to_s()]
    next if field_plain == nil
    fields[field_name] = plain_to_obj(
        field_plain, type, name ? "#{name}.#{field_name}" : field_name.to_s(), game)
  end
  return new(fields)
end

.plain_to_obj(plain, type, name, game) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/mjai/jsonizable.rb', line 41

def self.plain_to_obj(plain, type, name, game)
  case type
    when :number
      validate_class(plain, Integer, name)
      return plain
    when :string
      validate_class(plain, String, name)
      return plain
    when :string_or_null
      validate(plain.is_a?(String) || plain == nil, "#{name} must be String or null.")
      return plain
    when :boolean
      validate(
          plain.is_a?(TrueClass) || plain.is_a?(FalseClass),
          "#{name} must be either true or false.")
      return plain
    when :symbol
      validate_class(plain, String, name)
      validate(!plain.empty?, "#{name} must not be empty.")
      return plain.intern()
    when :player
      validate_class(plain, Integer, name)
      validate((0...4).include?(plain), "#{name} must be either 0, 1, 2 or 3.")
      return game.players[plain]
    when :pai
      validate_class(plain, String, name)
      begin
        return Pai.new(plain)
      rescue ArgumentError => ex
        raise(ValidationError, "Error in %s: %s" % [name, ex.message])
      end
    when :yaku
      validate_class(plain, Array, name)
      validate(
          plain.size == 2 && plain[0].is_a?(String) && plain[1].is_a?(Integer),
          "#{name} must be an array of [String, Integer].")
      validate(!plain[0].empty?, "#{name}[0] must not be empty.")
      return [plain[0].intern(), plain[1]]
    when :action
      return from_plain(plain, name, game)
    when :numbers
      return plains_to_objs(plain, :number, name, game)
    when :strings
      return plains_to_objs(plain, :string, name, game)
    when :strings_or_nulls
      return plains_to_objs(plain, :string_or_null, name, game)
    when :booleans
      return plains_to_objs(plain, :boolean, name, game)
    when :symbols
      return plains_to_objs(plain, :symbol, name, game)
    when :pais
      return plains_to_objs(plain, :pai, name, game)
    when :pais_list
      return plains_to_objs(plain, :pais, name, game)
    when :yakus
      return plains_to_objs(plain, :yaku, name, game)
    when :actions
      return plains_to_objs(plain, :action, name, game)
    else
      raise("unknown type")
  end
end

.plains_to_objs(plains, type, name, game) ⇒ Object



104
105
106
107
108
109
# File 'lib/mjai/jsonizable.rb', line 104

def self.plains_to_objs(plains, type, name, game)
  validate_class(plains, Array, name)
  return plains.each_with_index().map() do |c, i|
    plain_to_obj(c, type, "#{name}[#{i}]", game)
  end
end

.validate(criterion, message) ⇒ Object

Raises:



111
112
113
# File 'lib/mjai/jsonizable.rb', line 111

def self.validate(criterion, message)
  raise(ValidationError, message) if !criterion
end

.validate_class(plain, klass, name) ⇒ Object



115
116
117
# File 'lib/mjai/jsonizable.rb', line 115

def self.validate_class(plain, klass, name)
  validate(plain.is_a?(klass), "%s must be %p." % [name, klass])
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



179
180
181
# File 'lib/mjai/jsonizable.rb', line 179

def ==(other)
  return self.class == other.class && @fields == other.fields
end

#hashObject



185
186
187
# File 'lib/mjai/jsonizable.rb', line 185

def hash
  return @fields.hash
end

#merge(hash) ⇒ Object



164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/mjai/jsonizable.rb', line 164

def merge(hash)
  fields = @fields.dup()
  for name, value in hash
    if !@@field_specs.any?(){ |n, t| n == name }
      raise(ArgumentError, "unknown field: %p" % k)
    end
    if value == nil
      fields.delete(name)
    else
      fields[name] = value
    end
  end
  return self.class.new(fields)
end

#to_jsonObject Also known as: to_s



130
131
132
# File 'lib/mjai/jsonizable.rb', line 130

def to_json()
  return JSON.dump(to_plain())
end

#to_plainObject



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/mjai/jsonizable.rb', line 134

def to_plain()
  hash = {}
  for name, type in @@field_specs
    obj = @fields[name]
    next if obj == nil
    case type
      when :symbol, :pai
        plain = obj.to_s()
      when :player
        plain = obj.id
      when :symbols, :pais
        plain = obj.map(){ |a| a.to_s() }
      when :pais_list
        plain = obj.map(){ |o| o.map(){ |a| a.to_s() } }
      when :yakus
        plain = obj.map(){ |s, n| [s.to_s(), n] }
      when :actions
        plain = obj.map(){ |a| a.to_plain() }
      when :number, :numbers, :string, :strings, :string_or_null, :strings_or_nulls, :boolean, :booleans
        plain = obj
      else
        raise("unknown type")
    end
    hash[name.to_s()] = plain
  end
  return hash
end