Class: Zold::Score

Inherits:
Object
  • 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.now, 'localhost', 80, 'NOPREFIX@ffffffffffffffff')

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(time, host, port, invoice, suffixes = [], strength: STRENGTH) ⇒ Score

time: UTC ISO 8601 string



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/zold/score.rb', line 37

def initialize(time, host, port, invoice, suffixes = [], strength: STRENGTH)
  raise "Invalid host name: #{host}" unless host =~ /^[a-z0-9\.-]+$/
  raise 'Time must be of type Time' unless time.is_a?(Time)
  raise 'Port must be of type Integer' unless port.is_a?(Integer)
  raise "Invalid TCP port: #{port}" if port <= 0 || port > 65_535
  raise "Invoice '#{invoice}' has wrong format" unless invoice =~ /^[a-zA-Z0-9]{8,32}@[a-f0-9]{16}$/
  @time = time
  @host = host
  @port = port
  @invoice = invoice
  @suffixes = suffixes
  @strength = strength
end

Instance Attribute Details

#hostObject (readonly)

Returns the value of attribute host.



35
36
37
# File 'lib/zold/score.rb', line 35

def host
  @host
end

#invoiceObject (readonly)

Returns the value of attribute invoice.



35
36
37
# File 'lib/zold/score.rb', line 35

def invoice
  @invoice
end

#portObject (readonly)

Returns the value of attribute port.



35
36
37
# File 'lib/zold/score.rb', line 35

def port
  @port
end

#strengthObject (readonly)

Returns the value of attribute strength.



35
36
37
# File 'lib/zold/score.rb', line 35

def strength
  @strength
end

#timeObject (readonly)

Returns the value of attribute time.



35
36
37
# File 'lib/zold/score.rb', line 35

def time
  @time
end

Class Method Details

.parse(text) ⇒ Object



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

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.parse(m[:time]), m[:host],
    m[:port].to_i, m[:invoice],
    m[:suffixes].split(' '),
    strength: m[:strength].to_i
  )
end

.parse_json(json) ⇒ Object



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

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.parse(json['time']), json['host'],
    json['port'], json['invoice'], json['suffixes'],
    strength: json['strength']
  )
end

.parse_text(text) ⇒ Object



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

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

Instance Method Details

#age_hoursObject



166
167
168
# File 'lib/zold/score.rb', line 166

def age_hours
  (Time.now - @time) / 60
end

#expired?Boolean

Returns:

  • (Boolean)


170
171
172
# File 'lib/zold/score.rb', line 170

def expired?
  @time < Time.now - 24 * 60 * 60
end

#hashObject



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

def hash
  raise 'Score has zero value, there is no hash' if @suffixes.empty?
  @suffixes.reduce(prefix) do |pfx, suffix|
    Digest::SHA256.hexdigest(pfx + ' ' + suffix)[0, 63]
  end
end

#nextObject



152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/zold/score.rb', line 152

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

#prefixObject



174
175
176
# File 'lib/zold/score.rb', line 174

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

#reduced(max = 4) ⇒ Object



145
146
147
148
149
150
# File 'lib/zold/score.rb', line 145

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

#to_hObject



131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/zold/score.rb', line 131

def to_h
  {
    value: value,
    host: @host,
    port: @port,
    invoice: @invoice,
    time: @time.utc.iso8601,
    suffixes: @suffixes,
    strength: @strength,
    hash: value.zero? ? nil : hash,
    minutes: ((Time.now - @time) / 60).to_i
  }
end

#to_sObject



120
121
122
123
124
125
126
127
128
129
# File 'lib/zold/score.rb', line 120

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

#to_textObject



107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/zold/score.rb', line 107

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)


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

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

#valueObject



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

def value
  @suffixes.length
end