Class: Zold::Score

Inherits:
Dry::Struct
  • Object
show all
Defined in:
lib/zold/score.rb

Overview

Score

Constant Summary collapse

STRENGTH =

Default strength for the entire system, in production mode.

6
ZERO =

The default no-value score.

Score.new(time: Time.now, host: 'localhost', port: 80, invoice: 'NOPREFIX@ffffffffffffffff')

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.parse(text) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/zold/score.rb', line 66

def self.parse(text)
  re = Regexp.new(
    '^' + [
      '([0-9]+)/(?<strength>[0-9]+):',
      ' (?<time>[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z)',
      ' (?<host>[0-9a-z\.\-]+)',
      ' (?<port>[0-9]+)',
      ' (?<invoice>[a-zA-Z0-9]{8,32}@[a-f0-9]{16})',
      '(?<suffixes>( [a-zA-Z0-9]+)*)'
    ].join + '$'
  )
  m = re.match(text.strip)
  raise "Invalid score '#{text}', doesn't match: #{re}" if m.nil?
  Score.new(
    time: Time.parse(m[:time]), host: m[:host],
    port: m[:port].to_i, invoice: m[:invoice],
    suffixes: m[:suffixes].split(' '),
    strength: m[:strength].to_i
  )
end

.parse_json(json) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/zold/score.rb', line 53

def self.parse_json(json)
  raise "Time in JSON is broken: #{json}" unless json['time'] =~ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/
  raise "Host is wrong: #{json}" unless json['host'] =~ /^[0-9a-z\.\-]+$/
  raise "Port is wrong: #{json}" unless json['port'].is_a?(Integer)
  raise "Invoice is wrong: #{json}" unless json['invoice'] =~ /^[a-zA-Z0-9]{8,32}@[a-f0-9]{16}$/
  raise "Suffixes not array: #{json}" unless json['suffixes'].is_a?(Array)
  Score.new(
    time: Time.parse(json['time']), host: json['host'],
    port: json['port'], invoice: json['invoice'], suffixes: json['suffixes'],
    strength: json['strength']
  )
end

.parse_text(text) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
# File 'lib/zold/score.rb', line 87

def self.parse_text(text)
  parts = text.split(' ', 7)
  Score.new(
    time: Time.at(parts[1].hex),
    host: parts[2],
    port: parts[3].hex,
    invoice: "#{parts[4]}@#{parts[5]}",
    suffixes: parts[6] ? parts[6].split(' ') : [],
    strength: parts[0].to_i
  )
end

Instance Method Details

#ageObject



178
179
180
# File 'lib/zold/score.rb', line 178

def age
  Time.now - time
end

#expired?(hours = 24) ⇒ Boolean

Returns:

  • (Boolean)


182
183
184
# File 'lib/zold/score.rb', line 182

def expired?(hours = 24)
  age > hours * 60 * 60
end

#hashObject



99
100
101
102
103
104
# File 'lib/zold/score.rb', line 99

def hash
  raise 'Score has zero value, there is no hash' if suffixes.empty?
  suffixes.reduce(prefix) do |pfx, suffix|
    OpenSSL::Digest::SHA256.new("#{pfx} #{suffix}").hexdigest
  end
end

#nextObject



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/zold/score.rb', line 158

def next
  raise 'This score is not valid' unless valid?
  idx = 0
  loop do
    suffix = idx.to_s(16)
    score = Score.new(
      time: time, host: host, port: port, invoice: invoice, suffixes: suffixes + [suffix],
      strength: strength
    )
    return score if score.valid?
    if score.expired?
      return Score.new(
        time: Time.now, host: host, port: port, invoice: invoice,
        suffixes: [], strength: strength
      )
    end
    idx += 1
  end
end

#prefixObject



186
187
188
# File 'lib/zold/score.rb', line 186

def prefix
  "#{time.utc.iso8601} #{host} #{port} #{invoice}"
end

#reduced(max = 4) ⇒ Object



151
152
153
154
155
156
# File 'lib/zold/score.rb', line 151

def reduced(max = 4)
  Score.new(
    time: time, host: host, port: port, invoice: invoice,
    suffixes: suffixes[0..[max, suffixes.count].min - 1], strength: strength, created: nil
  )
end

#to_hObject



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/zold/score.rb', line 134

def to_h
  {
    value: value,
    host: host,
    port: port,
    invoice: invoice,
    time: time.utc.iso8601,
    suffixes: suffixes,
    strength: strength,
    hash: value.zero? ? nil : hash,
    expired: expired?,
    valid: valid?,
    age: (age / 60).round,
    created: created.utc.iso8601
  }
end

#to_mnemoObject



106
107
108
# File 'lib/zold/score.rb', line 106

def to_mnemo
  "#{value}:#{time.strftime('%H%M')}"
end

#to_sObject



123
124
125
126
127
128
129
130
131
132
# File 'lib/zold/score.rb', line 123

def to_s
  [
    "#{value}/#{strength}:",
    time.utc.iso8601,
    host,
    port,
    invoice,
    suffixes.join(' ')
  ].join(' ').strip
end

#to_textObject



110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/zold/score.rb', line 110

def to_text
  pfx, bnf = invoice.split('@')
  [
    strength,
    time.to_i.to_s(16),
    host,
    port.to_s(16),
    pfx,
    bnf,
    suffixes.join(' ')
  ].join(' ')
end

#valid?Boolean

Returns:

  • (Boolean)


190
191
192
# File 'lib/zold/score.rb', line 190

def valid?
  suffixes.empty? || hash.end_with?('0' * strength)
end

#valueObject



194
195
196
# File 'lib/zold/score.rb', line 194

def value
  suffixes.length
end

#zero?Boolean

Returns:

  • (Boolean)


198
199
200
# File 'lib/zold/score.rb', line 198

def zero?
  equal?(Score::ZERO)
end