Last active
July 19, 2016 07:34
-
-
Save bibendi/d3facbc772b1cb6cf9872c7e3ecfb7c1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# coding: utf-8 | |
gem "activesupport" | |
gem "optparse-range" | |
gem "tty-table" | |
gem "ascii_charts" | |
require "optparse" | |
require "optparse/time" | |
require "optparse/range" | |
require "active_support/all" | |
require "tty-table" | |
require "ascii_charts" | |
options = {} | |
opt_parser = OptionParser.new do |opt| | |
opt.banner = 'Usage: cosorter OPTIONS' | |
opt.separator '' | |
opt.separator 'Options' | |
opt.on('-h', '--help', 'Help') do | |
puts opt_parser | |
exit | |
end | |
opt.on('--ids x,y,z', Array, 'Product ids') do |value| | |
options[:ids] = value.map(&:to_i) | |
end | |
opt.on('--start DATE', Time, 'Start time') do |value| | |
options[:start] = value | |
end | |
opt.on('--duration DAYS', Integer, 'Number of days (default: 1 day)') do |value| | |
options[:period] = value.days | |
end | |
opt.on('--threshold MINUTES', Integer, 'Threshold (default: 15 minutes)') do |value| | |
options[:threshold] = value.minutes | |
end | |
opt.on('--peak H:M-H:M', OptionParser::TimeRange, 'Calculate ranks only for this daily interval') do |value| | |
options[:peak] = value | |
end | |
opt.on('--chart', 'Draw charts') do | |
options[:show_chart] = true | |
end | |
end | |
begin | |
opt_parser.parse! | |
mandatory = [:ids, :start] | |
missing = mandatory.select{ |param| options[param].nil? } | |
raise OptionParser::MissingArgument, missing.join(', ') unless missing.empty? | |
rescue OptionParser::ParseError => e | |
puts e | |
puts opt_parser | |
exit | |
end | |
options[:period] ||= 1.day | |
options[:threshold] ||= 15.minutes | |
options[:show_chart] ||= false | |
def peak_cover?(current_time, peak) | |
current_peak = Range.new( | |
current_time.change(hour: peak.begin.hour, min: peak.begin.min), | |
current_time.change(hour: peak.end.hour, min: peak.end.min) | |
) | |
current_peak.cover?(current_time) | |
end | |
def calculate(current_time, ids, tty_table) | |
secs = (current_time - current_time.at_beginning_of_week).to_i.nonzero? || 1 | |
factor = ((Math.cos(secs) + 1) * 360).round + current_time.to_date.cweek | |
scores = ids.map do |product_id| | |
Math.cos(product_id.modulo(factor)) | |
end | |
sorted = scores.sort.uniq.reverse | |
ranks = scores.map { |e| sorted.index(e) + 1 } | |
tty_table << [current_time] + ranks | |
end | |
def totals(ids, tty_table) | |
rows = tty_table.rows | |
totals = [] | |
ids.size.times do |i| | |
totals << rows.sum { |row| row[i + 1] == 1 ? 1 : 0 } | |
end | |
tty_table << ["Total first times"] + totals | |
all_totals = totals.sum | |
tty_table << ["Total first times (%)"] + totals.map { |e| (e / all_totals.to_f * 100).round } | |
end | |
def chart(ids, tty_table) | |
ids.each_with_index do |product_id, i| | |
plots = [] | |
tty_table.rows[0..-3].each_with_index { |row, index| plots << [row[0].hour, row[i + 1]] } | |
puts AsciiCharts::Cartesian.new(plots, title: product_id.to_s).draw | |
end | |
end | |
current_time = options.fetch(:start) | |
finish_time = current_time + options.fetch(:period) | |
ids = options.fetch(:ids) | |
threshold = options.fetch(:threshold) | |
only_peak = !options[:peak].nil? | |
tty_table = TTY::Table.new(header: ["Time"] + ids.map(&:to_s)) | |
while current_time < finish_time | |
if !only_peak || peak_cover?(current_time, options[:peak]) | |
calculate(current_time, ids, tty_table) | |
end | |
current_time += threshold | |
end | |
totals(ids, tty_table) | |
puts tty_table.render(:ascii, alignment: [:center]) | |
chart(ids, tty_table) if options[:show_chart] |
# ./cosorter --ids 27870955,46814369,52062455,38575395 --start 2016.07.11 --duration 2 --threshold 15 --peak 10:00-17:00 --chart
+-------------------------+--------+--------+--------+--------+
| Time |27870955|46814369|52062455|38575395|
+-------------------------+--------+--------+--------+--------+
|2016-07-11 10:00:00 +0500| 4 | 2 | 1 | 3 |
|2016-07-11 10:15:00 +0500| 3 | 4 | 1 | 2 |
|2016-07-11 10:30:00 +0500| 4 | 2 | 3 | 1 |
|2016-07-11 10:45:00 +0500| 4 | 2 | 3 | 1 |
|2016-07-11 11:00:00 +0500| 3 | 2 | 1 | 4 |
|2016-07-11 11:15:00 +0500| 3 | 2 | 1 | 1 |
|2016-07-11 11:30:00 +0500| 1 | 3 | 2 | 4 |
|2016-07-11 11:45:00 +0500| 4 | 1 | 3 | 2 |
|2016-07-11 12:00:00 +0500| 2 | 4 | 3 | 1 |
|2016-07-11 12:15:00 +0500| 3 | 1 | 4 | 2 |
|2016-07-11 12:30:00 +0500| 2 | 4 | 3 | 1 |
|2016-07-11 12:45:00 +0500| 1 | 3 | 4 | 2 |
|2016-07-11 13:00:00 +0500| 2 | 4 | 3 | 1 |
|2016-07-11 13:15:00 +0500| 1 | 2 | 4 | 3 |
|2016-07-11 13:30:00 +0500| 2 | 1 | 4 | 3 |
|2016-07-11 13:45:00 +0500| 1 | 3 | 4 | 2 |
|2016-07-11 14:00:00 +0500| 1 | 2 | 3 | 4 |
|2016-07-11 14:15:00 +0500| 1 | 3 | 2 | 4 |
|2016-07-11 14:30:00 +0500| 3 | 1 | 2 | 4 |
|2016-07-11 14:45:00 +0500| 2 | 1 | 4 | 3 |
|2016-07-11 15:00:00 +0500| 1 | 2 | 4 | 3 |
|2016-07-11 15:15:00 +0500| 3 | 4 | 2 | 1 |
|2016-07-11 15:30:00 +0500| 2 | 3 | 4 | 1 |
|2016-07-11 15:45:00 +0500| 3 | 1 | 2 | 4 |
|2016-07-11 16:00:00 +0500| 4 | 1 | 3 | 2 |
|2016-07-11 16:15:00 +0500| 1 | 4 | 3 | 2 |
|2016-07-11 16:30:00 +0500| 1 | 4 | 2 | 3 |
|2016-07-11 16:45:00 +0500| 1 | 4 | 3 | 2 |
|2016-07-11 17:00:00 +0500| 1 | 3 | 2 | 4 |
|2016-07-12 10:00:00 +0500| 4 | 3 | 1 | 2 |
|2016-07-12 10:15:00 +0500| 1 | 4 | 2 | 3 |
|2016-07-12 10:30:00 +0500| 3 | 2 | 4 | 1 |
|2016-07-12 10:45:00 +0500| 2 | 4 | 1 | 3 |
|2016-07-12 11:00:00 +0500| 2 | 1 | 3 | 4 |
|2016-07-12 11:15:00 +0500| 4 | 2 | 3 | 1 |
|2016-07-12 11:30:00 +0500| 3 | 4 | 1 | 2 |
|2016-07-12 11:45:00 +0500| 2 | 4 | 3 | 1 |
|2016-07-12 12:00:00 +0500| 3 | 4 | 2 | 1 |
|2016-07-12 12:15:00 +0500| 4 | 2 | 1 | 3 |
|2016-07-12 12:30:00 +0500| 1 | 3 | 4 | 2 |
|2016-07-12 12:45:00 +0500| 3 | 2 | 1 | 4 |
|2016-07-12 13:00:00 +0500| 4 | 1 | 3 | 2 |
|2016-07-12 13:15:00 +0500| 4 | 2 | 3 | 1 |
|2016-07-12 13:30:00 +0500| 1 | 2 | 3 | 4 |
|2016-07-12 13:45:00 +0500| 1 | 3 | 2 | 4 |
|2016-07-12 14:00:00 +0500| 1 | 4 | 2 | 3 |
|2016-07-12 14:15:00 +0500| 2 | 4 | 1 | 3 |
|2016-07-12 14:30:00 +0500| 2 | 4 | 1 | 3 |
|2016-07-12 14:45:00 +0500| 2 | 1 | 3 | 4 |
|2016-07-12 15:00:00 +0500| 1 | 4 | 3 | 2 |
|2016-07-12 15:15:00 +0500| 3 | 4 | 1 | 2 |
|2016-07-12 15:30:00 +0500| 2 | 3 | 1 | 4 |
|2016-07-12 15:45:00 +0500| 1 | 4 | 3 | 2 |
|2016-07-12 16:00:00 +0500| 1 | 3 | 2 | 4 |
|2016-07-12 16:15:00 +0500| 3 | 1 | 2 | 4 |
|2016-07-12 16:30:00 +0500| 2 | 3 | 4 | 1 |
|2016-07-12 16:45:00 +0500| 3 | 2 | 1 | 4 |
|2016-07-12 17:00:00 +0500| 2 | 3 | 1 | 4 |
| Total first times | 19 | 11 | 15 | 14 |
| Total first times (%) | 32 | 19 | 25 | 24 |
+-------------------------+--------+--------+--------+--------+
27870955
4| * * * * * * * * * *
3| * * * * * * * * * * * * * *
2| * * * * * * * * * * * * * * *
1| * * * * * * * * * * * * * * * * * * *
0+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
10 10 10 10 11 11 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15 15 15 16 16 16 16 17 10 10 10 10 11 11 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15 15 15 16 16 16 16 17
46814369
4| * * * * * * * * * * * * * * * * * * *
3| * * * * * * * * * * * * *
2| * * * * * * * * * * * * * * *
1| * * * * * * * * * * *
0+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
10 10 10 10 11 11 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15 15 15 16 16 16 16 17 10 10 10 10 11 11 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15 15 15 16 16 16 16 17
52062455
4| * * * * * * * * * * *
3| * * * * * * * * * * * * * * * * * * *
2| * * * * * * * * * * * * *
1| * * * * * * * * * * * * * * *
0+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
10 10 10 10 11 11 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15 15 15 16 16 16 16 17 10 10 10 10 11 11 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15 15 15 16 16 16 16 17
38575395
4| * * * * * * * * * * * * * * * * *
3| * * * * * * * * * * * *
2| * * * * * * * * * * * * * * *
1| * * * * * * * * * * * * * *
0+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
10 10 10 10 11 11 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15 15 15 16 16 16 16 17 10 10 10 10 11 11 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15 15 15 16 16 16 16 17
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
27870955 - Первая Строительная База
46814369 - ИнтерМетПром
52062455 - ТД Гефест
38575395 - Стальинвест