#!/usr/bin/env ruby require 'date' # TODO: this. # Take a file as first argument, which is to be the file biblio.csv, containing # all books read. Then formats this as a table. It sorts the books in # the order [Ongoing, Completed, Yet to Read], and replaces several values with # ones more appropriate for viewing pleasure. # For the final column (index: 11, zero-indexed) we replace the contents with a # link. So rd/the-progress-of-a-crime becomes # For column 3 (Part), this is rounded as special logic. # \n" exit end # def do_header(h: str): str # Returns the rows of the table corresponding to the header. def do_header(h) s = "\t\n" values = h.split($delim) values.each_with_index do |value, idx| next if idx == 0 or idx == 6 or idx == 7 or idx == 8 or idx == 9 s << ("\t\t" + value + "\n") end s << "\t\n" return s end # Make the string look sexy, ooh la la. def sexify(val) # Round integers if they end .00. if val.end_with? ".00" then integral = val.to_i unless integral == 0 return integral.to_s end end # Transform strings. if $status_transform.has_key? (val) return $status_transform[val] end if $form_transform.has_key? (val) return $form_transform[val] end if $ownership_transform.has_key? (val) return $ownership_transform[val] end if $general_transform.has_key? (val) return $general_transform[val] end return val end ret="" header="" # Contains the buckets into which to put the entries. unknown = [] # typeof(unknown) == array[str] known = {} # typeof(known) == Hash[str => array[str]] def written_month_of(ym) # Takes, e.g. "2023-09" and returns "September 2023". Invariant: entry must # be of form "YYYY-MM". month = ym[-2..-1] ret = "" month_name = Date::MONTHNAMES[month.to_i] ret << month_name << " " << ym[0..3] return ret end def wrap_entries_in_table(entries, header) # Call after string made of all entries. This fn wraps them into the table. ret = "" ret << "\n" \ << header \ << entries \ << "
\n" return ret end def make_html_entry(entry) # Makes a singular entry. ret = "" ret << "\t\n" entry.split($delim).each_with_index do |e, i| next if i == 0 or i == 6 or i == 7 or i == 8 or i == 9 e = e.delete "\n" if i == 11 and e != "N/A" then ret << "\t\t
Link\n" else ret << "\t\t" \ << sexify(e) \ << "\n" end end ret << "\t\n" return ret end File.foreach(ARGV[0]).with_index do |line, line_num| # 0. If entry not completed, skip, otherwise ...; [done] # 1. Figure out what month the line corresponds to; # 2. Chuck line into a bucket corresponding to entries in that month; # 3. Sorting that bucket into the right month, and make the table out of the # entries. if line_num == 0 then # Must go first, otherwise skipped by checks below. header << do_header(line) end next if line == "\n" or line == "\t" or line == "" or line == " " or line == $delim next if not line.include? "completed;" finished_date = line.split($delim)[5] if finished_date == "" or finished_date == "\t" or finished_date == "N/A" then unknown = unknown.append line else # Invariant: everything completed is either unknown date, or has at least # a year and a month (but not necessarily a day). We use this, e.g. # "2023-01", as the index for the month. index = finished_date[0..6] # It is possible for the index not to be added here, so if this is the case # just add the index as [] and then we directly append to what we've just # added. if not known.has_key? (index) known[index] = [] end # And now we can append. known[index] = (known[index] << line) end end # Sort hash, so we can simply iterate over it. known = known.sort.reverse.to_h # Make HTML for "Unknown"s unknown = unknown.map! { |entry| make_html_entry(entry) }.join ("\n") unknown_table = wrap_entries_in_table(unknown, header) # typeof == str unkn_ret = "" unkn_ret << "

Unknown

\n" \ << unknown_table kn_rets = [] # Make HTML for each month. known.each do |key, values| # Here, values is an array of all entries. We want to merge then together, # and thereby get the table. values = values.map! { |value| make_html_entry(value) }.join ("\n") known_table = wrap_entries_in_table(values, header) # typeof == str kn_ret = "" kn_ret << "

" \ << written_month_of(key) \ << "

\n" \ << known_table kn_rets = kn_rets.append(kn_ret) end # File.foreach(ARGV[0]).with_index do |line, line_num| # next if line == "\n" or line == "\t" or line == "" or line == " " or line == $delim # # # Handle the first line - the header. # if line_num == 0 then # header << do_header(line) # else # # We need to figure out whether it is ongoing, completed, or yet to read. # # To do this, we will check if the corresponding string is in the line. # if line.include? "completed;" then # target = table_cmp # elsif line.include? "ongoing;" then # target = table_ongoing # elsif line.include? "dropped;" then # target = table_drp # else # target = table_rest # end # # end # end # Echo the file. puts kn_rets puts unkn_ret