123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- # Copyright 2024 Henrique Paone
- #
- # This file is part of Tanki.
- #
- # Tanki is free software: you can redistribute it and/or modify it under the
- # terms of the GNU General Public License as published by the Free Software
- # Foundation, either version 3 of the License, or (at your option) any later
- # version.
- #
- # Tanki is distributed in the hope that it will be useful, but WITHOUT ANY
- # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
- # PARTICULAR PURPOSE. See the GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License along with
- # Tanki. If not, see <https://www.gnu.org/licenses/>.
- require 'date'
- require_relative 'tui/tui.rb'
- require_relative 'error.rb'
- class Card
- include Tui
- include Error
-
- attr_reader :title, :prompt, :answer
- attr_writer :stage, :last_review
- Regexes = {
- # Everything after a # is ignore, \# is allowed
- :comment => /(?<!\\)#.*/,
-
- # The stage is an arbitrary number
- :stage => /^Stage:\s*\K\d+/,
-
- # Gets the date in the format year-month-day
- :last_review => /^LastReview:\s*\K\d{4}-\d{1,2}-\d{1,2}/,
-
- # Matches everything between two %. To get the answer, we apply this match
- # then check in the $' variable and to get the title we get until the first \n
- :prompt => /%\K(.*)\K%/m
- }
- def method_missing(m, *args, &block)
- show(false, *args) if m == :show_prompt
- show(true, *args) if m == :show_answer
- end
-
- def initialize(file)
- @file = File.new(file)
- @text = @file.read
- parse
- end
- def show(show_answer, amt)
- lines, cols = *IO.console.winsize
- cstart = lstart = margin = 5
- lend = lines - margin
- cend = cols - margin
- lbeg = cstart + 1
-
- IO.console.clear_screen
- draw_box(cstart, lstart, lend, cend)
- lstart += 1
-
- move_cursor(lstart, lbeg)
- print @file.path
- card_str = 'cards'
- card_str = 'card' if amt == 1
- print_line_before("#{ amt } #{ card_str } pending", lstart, cend - 1)
- lstart += 1
-
- draw_vline_inbox(cstart, cend, lstart)
- lstart += 3
- lstart = print_centered(@prompt, lstart, lbeg, cstart, cend - 1)
-
- lstart += ((lend - lstart) / 2) - 2
- print_centered(@answer, lstart, lbeg, cstart, cend - 1) if show_answer
- options = {
- right: 'r: Right',
- wrong: 'w: Wrong',
- quit: 'q: Quit',
- enter: '--ENTER--'
- }
-
- draw_vline_inbox(cstart, cend, lend - 2)
- move_cursor(lend - 1, lbeg)
- unless show_answer
- # Before asking to show the answer
- print options[:enter].center(cend - cstart - 1)
- else
- # After asking to show the answer
- print options[:right].center(cend - cstart - 1)
- move_cursor(lend - 1, lbeg)
- print options[:wrong]
- end
- print_line_before(options[:quit], lend - 1, cend - 1)
- move_cursor(lines, 1)
- end
- def parse
- text = @text.gsub(Regexes[:comment], '')
-
- last_review = text.scan(Regexes[:last_review]).first
- stage = text.scan(Regexes[:stage]).first
- text.gsub!("Stage: #{ stage }", '')
- text.gsub!("LastReview: #{ last_review }", '')
- # Note: prompt must be the last scan so we can fetch the answer using $'
- prompt = text.scan(Regexes[:prompt]).first
- raise ParsingError, Err_msgs[:parse ] % { file: @file.path } if prompt.nil?
-
- @stage = stage.nil? ? 0 : stage.to_i
- begin
- @last_review = last_review.nil? ? Date.today : Date.strptime(last_review, '%Y-%m-%d')
- rescue Date::Error
- raise BadValue, Err_msgs[:bad_date] % { file: @file }
- end
- @prompt = prompt.first
- @answer = $'
- end
- def write
- text = @text.split("\n")
- stage_idx = text.index do |line|
- line.match?(Regexes[:stage])
- end
- last_review_idx = text.index do |line|
- line.match?(Regexes[:last_review])
- end
- if stage_idx.nil?
- text << ""
- text << "# Values for internal tanki use, dont touch them unless you know what you're doing"
- text << "Stage: #{ @stage }"
- else
- text[stage_idx] = "Stage: #{ @stage }"
- end
- if last_review_idx.nil?
- text << "LastReview: #{ @last_review }"
- else
- text[last_review_idx] = "LastReview: #{ @last_review }"
- end
- File.open(@file.path, 'w').write(text.join("\n") << "\n")
- @file.close
- end
-
- def pending?
- Date.today >= @last_review + stage_dif
- end
- def check_syntax
- end
- def reset
- @stage = 0
- end
- def incr
- @stage += 1
- end
- def stage_dif
- dif = count = 0
- skip = false
- while count != @stage
- unless skip
- dif += 1
- skip = true
- else
- skip = false
- end
- count += 1
- end
- dif
- end
- end
|