Sprichwoerter 0.1 → 1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,47 @@
1
+ #encoding: UTF-8
2
+
3
+ =begin
4
+ /***************************************************************************
5
+ * ©2014-2019, Michael Uplawski <michael.uplawski@uplawski.eu> *
6
+ * *
7
+ * This program is free software; you can redistribute it and/or modify *
8
+ * it under the terms of the GNU General Public License as published by *
9
+ * the Free Software Foundation; either version 3 of the License, or *
10
+ * (at your option) any later version. *
11
+ * *
12
+ * This program is distributed in the hope that it will be useful, *
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15
+ * GNU General Public License for more details. *
16
+ * *
17
+ * You should have received a copy of the GNU General Public License *
18
+ * along with this program; if not, write to the *
19
+ * Free Software Foundation, Inc., *
20
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21
+ ***************************************************************************/
22
+ =end
23
+
24
+ =begin
25
+ Functions which rearrange an array.
26
+ =end
27
+ module Rearranging
28
+
29
+ public
30
+ # ... guess
31
+ def randomize
32
+ if( self.respond_to?(:to_ary) )
33
+ size = self.length
34
+ original_list = self.dup
35
+ random_list = Array.new
36
+ while(random_list.size < size) do
37
+ srand(Time::now.nsec)
38
+ index = rand(original_list.size)
39
+ item = original_list.delete_at(index)
40
+ random_list << item
41
+ end
42
+ self.replace(random_list)
43
+ else
44
+ raise TypeError.new('can only randomize Array, not ' << self.class.name)
45
+ end
46
+ end
47
+ end
@@ -2,7 +2,7 @@
2
2
  #encoding: UTF-8
3
3
  =begin
4
4
  /***************************************************************************
5
- * ©2016-2016 Michael Uplawski <michael.uplawski@uplawski.eu> *
5
+ * ©2016-2019 Michael Uplawski <michael.uplawski@uplawski.eu> *
6
6
  * *
7
7
  * This program is free software; you can redistribute it and/or modify *
8
8
  * it under the terms of the GNU General Public License as published by *
@@ -21,39 +21,188 @@
21
21
  ***************************************************************************/
22
22
  =end
23
23
 
24
+ require_relative 'user_input'
25
+ require_relative 'argparser'
26
+ require_relative 'translating'
27
+ require_relative 'rearranging'
28
+ require_relative 'logging'
24
29
 
25
-
30
+ # Main application class.
26
31
  class SprichWoerter
27
- def initialize(lang='de')
28
- require_relative 'liste_' << lang
29
- box = %w~┌ ┐ └ ┘ ─ │~
30
- num_pvs = $proverbs.size
31
- srand(Time.new.to_i)
32
- first = ''
33
- until !first.empty?
34
- fi = rand(num_pvs)
35
- second = first = $proverbs[fi][0]
36
- si = fi
37
- end
38
- until (si != fi && $proverbs[si][0] != first && !second.empty?)
39
- si = rand(num_pvs)
40
- second = $proverbs[si][1]
41
- end
42
- =begin
43
- puts ($proverbs[fi].to_s << " (" << fi.to_s << ")")
44
- puts ($proverbs[si].to_s << " (" << si.to_s << ")")
45
- =end
46
- phr = first << ' ' << second << '.'
32
+ include Translating
33
+ self.extend( Logging)
34
+ @@log = self.init_logger(STDOUT)
35
+ # An object of this class acts as a functor. Calling new() is thus the only
36
+ # available access to all its functionality.
37
+ #def initialize(lang='de', action = :create)
38
+
39
+ def initialize(lang='de', args)
40
+ @lang = lang
41
+ @log = @@log
42
+ @options = ArgParser.parse(ARGV)
43
+ @log.debug("options are: " << @options.inspect)
44
+ listfile = 'liste' << '_' << @lang
45
+ # ------------- language is set --------------
46
+ @confdir = ENV['HOME'].dup << File::Separator << ".proverbs"
47
+
48
+ if(@options.list)
49
+ show_favorites
50
+ exit 0
51
+ end
52
+ user_list = @confdir.dup << File::Separator << listfile
53
+ # cosmetics
54
+ listrb = user_list << '.rb'
55
+
56
+ if File::exist?(listrb) && File.readable?(listrb)
57
+ require user_list
58
+ else
59
+ require_relative listfile
60
+ end
61
+ # ------------- proverbs are identified ---------
62
+ if @options.add
63
+ Adder.new(@lang, @options.add, *ARGV)
64
+ exit true
65
+ end
66
+
67
+ # borders
68
+ up_left = '┌'
69
+ up_right = '┐'
70
+ bottom_left = '└'
71
+ bottom_right = '┘'
72
+ hor = '─'
73
+ vert = '│'
74
+ srand(Time.now.nsec)
75
+ # group 0 or group 1 ?
76
+ sfx = [0, 1][rand(2)]
77
+ proverbs = eval("$proverbs" + sfx.to_s)
78
+ # This appears to improve the randomness :
79
+ # allow for the list of proverbs to be 'rearranged' ...
80
+ proverbs.extend(Rearranging)
81
+ # ... and do it, each time.
82
+ # This seeds the pseudo-random generator anew
83
+ proverbs.randomize
84
+ num_pvs = proverbs.size
85
+ first = ''
86
+ # Find 1 original proverb in the group.
87
+ until !first.empty?
88
+ # determine the index of an original proverb.
89
+ fi = rand(num_pvs)
90
+ # read the beginning of the proverb
91
+ second = first = proverbs[fi][0]
92
+ si = fi
93
+ end
94
+ srand(Time.now.nsec)
95
+ # Find a second proverb, different from the first.
96
+ until (si != fi && proverbs[si][0] != first && !second.empty?)
97
+ si = rand(num_pvs)
98
+ # read the end of the proverb
99
+ second = proverbs[si][1]
100
+ end
101
+ # Construct the new proverb.
102
+ phr = first << ' ' << second << '.'
103
+
104
+ #draw
105
+ len = phr.size
106
+ # TODO: Wrap text if needed, determine number of line-breaks, then draw 1
107
+ # border around all lines of text.
108
+ col = @options.color
109
+ puts "" << maybe_in_color(up_left << hor * len << up_right, col)
110
+ puts "" << maybe_in_color(vert, col) << phr << maybe_in_color(vert, col)
111
+ puts "" << maybe_in_color(bottom_left << hor * len << bottom_right, col)
112
+ # Allow the new proverb to be rated
113
+ qualify( phr) if @options.qualify
114
+ end
115
+
116
+ # This function wraps a call to eval(). It also verifies that a color is
117
+ # set, although a default should apply, if not.
118
+ def maybe_in_color(txt, color)
119
+ if @options.color
120
+ cmd = @options.color + ' "' << txt << '"'
121
+ eval (cmd)
122
+ else
123
+ txt
124
+ end
125
+ end
126
+
127
+ def show_favorites
128
+ puts read_qualifile[0].join("\n")
129
+ end
47
130
 
48
- #draw
49
- len = phr.size
131
+ # Find the file with the list of rated, generated proverbs. Returns
132
+ # an Array of those proverbs and the path to the file itself.
133
+ def read_qualifile
134
+ qualifile = @confdir.dup << File::Separator << 'qualifile_' << @lang
135
+ lines = Array.new
136
+ if(File.exist?(qualifile) )
137
+ msg = nil
138
+ if(!File.readable?(qualifile) )
139
+ msg = trl("ERROR") << '!' << trl("The file %s cannot be opened for reading!") %qualifile
140
+ elsif (!File.writable?(qualifile) )
141
+ msg = trl("ERROR") << '!' << trl("The file %s cannot be opened for writing!") %qualifile
142
+ end
143
+ if msg
144
+ puts msg
145
+ exit false
146
+ else
147
+ qf = File.open(qualifile, 'a+')
148
+ lines = qf.readlines(chomp:true)
149
+ end
150
+ else
151
+ if !File.exist?(@confdir)
152
+ Dir.mkdir(@confdir)
153
+ end
154
+ qf = File.new(qualifile, 'w')
155
+ end
156
+ qf.close
157
+ return lines, qualifile
158
+ end
50
159
 
51
- puts "" << box[0] << box[4] * len << box[1]
52
- puts "" << box[5] << phr << box[5]
53
- puts "" << box[2] << box[4] * len << box[3]
54
- end
160
+ # Rate a proverb. For the time, only a simple, positive rating is possible.
161
+ def qualify(phr)
162
+ # Create a cheap busy-indicator; Asynchronously count down from 5 to 1.
163
+ thr = Thread.new do
164
+ 5.downto(1) do |n|
165
+ print n
166
+ sleep 1
167
+ print "\b"
168
+ if(n == 1)
169
+ print("\n")
170
+ exit true
171
+ end
172
+ end
173
+ end
174
+ msg = trl("Push '+' for a positive rating") << ".\n"
175
+ puts msg
176
+ # Wait for user-input while the count-down is running.
177
+ # The loop serves to re
178
+ while thr.alive? do
179
+ user_input = wait_for_user
180
+ if ('+' == user_input.chr.downcase )
181
+ # Terminate the count-down, if the user pushed '+'
182
+ thr.terminate
183
+ qf = nil
184
+ lines, qf = read_qualifile
185
+ if (qf && !lines.include?(phr))
186
+ # add the latest generated proverb
187
+ File.write(qf, phr + "\n", :mode=>'a+')
188
+ puts "\b" << trl('Done')
189
+ exit true
190
+ end
191
+ # Handle Ctrl+c, Ctrl+d and Esc in the same way.
192
+ elsif [3,4,27].include? user_input
193
+ thr.terminate
194
+ puts "\n"
195
+ exit true
196
+ end
197
+ end
198
+ end
55
199
  end
56
200
 
57
201
  if __FILE__ == $0
58
- sp = SprichWoerter.new(ARGV[0])
202
+ if !ARGV.empty?
203
+ SprichWoerter.new(ARGV[0])
204
+ else
205
+ SprichWoerter.new('de')
206
+ end
59
207
  end
208
+ # EOF
@@ -0,0 +1,101 @@
1
+ #encoding: UTF-8
2
+ =begin
3
+ /***************************************************************************
4
+ * ©2011-2019, Michael Uplawski <michael.uplawski@uplawski.eu> *
5
+ * *
6
+ * This program is free software; you can redistribute it and/or modify *
7
+ * it under the terms of the GNU General Public License as published by *
8
+ * the Free Software Foundation; either version 3 of the License, or *
9
+ * (at your option) any later version. *
10
+ * *
11
+ * This program is distributed in the hope that it will be useful, *
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
+ * GNU General Public License for more details. *
15
+ * *
16
+ * You should have received a copy of the GNU General Public License *
17
+ * along with this program; if not, write to the *
18
+ * Free Software Foundation, Inc., *
19
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20
+ ***************************************************************************/
21
+ =end
22
+
23
+
24
+ RD = File.expand_path(File.dirname(__FILE__) ) + File::SEPARATOR if !defined?(RD)
25
+
26
+ require 'yaml'
27
+
28
+ # A way to produce translated text in a ruby-program.
29
+ # Translations are read from a file "translations" in the program folder.
30
+ module Translating
31
+ # There are better ways to extend a translated
32
+ # string, but I keep the 'wild-card' for
33
+ # historical reasons.
34
+
35
+ @@lang = nil
36
+ @@lang_file = format("%s%s", RD, 'LANG')
37
+ @@tr = YAML::load_file("#{RD}translations")
38
+
39
+ # find the current language-setting and return it.
40
+ def self.language()
41
+ if @@lang == nil
42
+ r = ENV['LANG']
43
+ if(r)
44
+ @@lang = r[0, 2]
45
+ elsif( File.exist?(@@lang_file) && File.readable?(@@lang_file) && File::size(@@lang_file) >= 2)
46
+ File::open(@@lang_file, 'r') {|f| @@lang = f.readline}
47
+ @@lang.chomp!.downcase! if @@lang
48
+ end
49
+ end
50
+ @@lang = 'en' if !@@lang
51
+ end
52
+
53
+ # Translate a string to the currently set langage.
54
+ # Note that the argument may contain a format-string
55
+ # in sprintf-syntax.
56
+ def self.trl(t)
57
+ Translating::language()
58
+ lt = @@tr[t]
59
+ if(lt)
60
+ lt = lt[@@lang]
61
+ else
62
+ # File.open('/tmp/mtf', 'a+') {|f| f << t << "\n"}
63
+ puts "\nTRANSLATION MISSING: \"" << t << "\""
64
+ end
65
+ lt ||= t
66
+ return lt
67
+ end
68
+
69
+ # Translate a string to the currently set langage.
70
+ # Note that the argument may contain a format-string
71
+ # in sprintf-syntax.
72
+ def trl(t )
73
+ Translating::trl(t)
74
+ end
75
+
76
+ # Translate in the given string only those words for which a translation
77
+ # is found.
78
+ # This is useful for mixed content like dates: "Friday, 8. July 2011".
79
+ # As the order changes with the locale, alphabetic content is matched and the
80
+ # remainder discarded.
81
+ def self::trl_words(str)
82
+ n_str = str.clone
83
+ loop do
84
+ m = str.match(/[[:alpha:]]+/)
85
+ break if !m
86
+ str.gsub!(m.to_s, '')
87
+ n_str.gsub!(m.to_s, trl(m.to_s))
88
+ end
89
+ return n_str
90
+ end
91
+ # Translate in the given string only those words for which a translation
92
+ # exists.
93
+ # This is useful for mixed content like dates: "Friday, 8. July 2011".
94
+ # As the order changes with the locale, alphabetic content is matched and the
95
+ # remainder discarded.
96
+ def trl_words(str)
97
+ Translating::trl_words(str)
98
+ end
99
+
100
+ end
101
+
@@ -0,0 +1,164 @@
1
+ list:
2
+ de: liste
3
+
4
+ Execute with option -h to see an option summary:
5
+ de: Starten Sie das Program mit -h um die Erklärung der Kommandozeilenargumente zu sehen.
6
+
7
+ invalid option:
8
+ de: Ungültiges Argument
9
+
10
+ missing argument:
11
+ de: Fehlender Wert
12
+
13
+ for option:
14
+ de: für Option
15
+
16
+ Error!:
17
+ de: Fehler!
18
+
19
+ Invalid color value:
20
+ de: Ungültiger Farbname
21
+
22
+ Singular or plural (s, p):
23
+ de: Singular oder Plural (s, p)
24
+
25
+ s:
26
+ de: s
27
+
28
+ p:
29
+ de: p
30
+
31
+ singular:
32
+ de: singular
33
+
34
+ plural:
35
+ de: plural
36
+
37
+ Cannot add the proverb, invalid argument:
38
+ de: Kann das Sprichwort nicht hinzufügen, ungültiges Argument
39
+
40
+ List %s has been updated:
41
+ de: Liste %s wurde aktualisiert
42
+
43
+ Push '+' for a positive rating:
44
+ de: Drücken Sie ‚+’, um das Sprichwort positiv zu bewerten
45
+
46
+ Done:
47
+ de: Fertig
48
+ a:
49
+ de: n
50
+
51
+ add:
52
+ de: neu
53
+
54
+ GROUP:
55
+ de: GRUPPE
56
+
57
+ LANG:
58
+ de: SPRACHE
59
+
60
+ f:
61
+ de: l
62
+
63
+ l:
64
+ de: s
65
+
66
+ Language:
67
+ de: Sprache
68
+
69
+ lang:
70
+ de: sprache
71
+
72
+ favorites:
73
+ de: liste
74
+
75
+ q:
76
+ de: w
77
+
78
+ qualify:
79
+ de: werten
80
+
81
+ c:
82
+ de: f
83
+
84
+ -c:
85
+ de: -f
86
+
87
+ color:
88
+ de: farbe
89
+
90
+ h:
91
+ de: h
92
+
93
+ help:
94
+ de: hilfe
95
+
96
+ Usage:
97
+ de: Syntax
98
+
99
+ Specific options:
100
+ de: Spezielle Optionen
101
+
102
+ Add real proverb to the base:
103
+ de: Neues Sprichwort in Stammdaten aufnehmen
104
+
105
+ Beginning of the proverb:
106
+ de: Anfang des Sprichworts
107
+
108
+ Ending of the proverb:
109
+ de: Ende des Sprichworts
110
+
111
+ Set language:
112
+ de: Sprache festlegen
113
+
114
+ Show favorites:
115
+ de: Best Bewertete auflisten
116
+
117
+ Qualify proverbs:
118
+ de: Sprichwörter bewerten
119
+
120
+ Use color in program-output (one of red, green, yellow, purple, cyan, blue, white, black):
121
+ de: Farbige Programmausgabe (eine von rot, grün, gelb, lila, cyan, blau, weiß, schwarz)
122
+
123
+ Common options:
124
+ de: Allgemeine Optionen
125
+
126
+ Show this message:
127
+ de: Diese Meldung anzeigen
128
+
129
+ v:
130
+ de: v
131
+
132
+ version:
133
+ de: version
134
+
135
+ Show version and program information:
136
+ de: Versionsinformationen anzeigen
137
+
138
+ COLOR:
139
+ de: FARBE
140
+
141
+ red:
142
+ de: rot
143
+
144
+ green:
145
+ de: grün
146
+
147
+ purple:
148
+ de: lila
149
+
150
+ yellow:
151
+ de: gelb
152
+
153
+ cyan:
154
+ de: cyan
155
+
156
+ blue:
157
+ de: blau
158
+
159
+ white:
160
+ de: weiß
161
+
162
+ black:
163
+ de: schwarz
164
+