jungi 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,193 @@
1
+ # JungI - A simple program for taking open source personality tests.
2
+ # Copyright (C) 2015 Mfrogy Starmade
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ # Global Question Module
18
+ module Question
19
+ # Question Type Enum
20
+ module Type
21
+ YESORNO = :yn
22
+ SCALE = :scale
23
+ end
24
+
25
+ # Question Answer Module
26
+ module Answer
27
+ YES = :yes
28
+ NO = :no
29
+
30
+ # Check value for yes or no value
31
+ def self.yes_or_no?(value)
32
+ if value == Question::Answer::YES || value == Question::Answer::NO
33
+ return true
34
+ else
35
+ return false
36
+ end
37
+ end
38
+
39
+ # Check value for scale value
40
+ def self.scale?(value)
41
+ if value == 1 || value == 2 || value == 3 || value == 4 || value == 5
42
+ return true
43
+ else
44
+ return false
45
+ end
46
+ end
47
+
48
+ # Reverse scale value
49
+ def self.reverse_scale(value)
50
+ unless Question::Answer.scale?(value)
51
+ fail "#{type} is not a proper scale!"
52
+ end
53
+ [5, 4, 3, 2, 1].to_a[value - 1]
54
+ end
55
+
56
+ # Checks value follows type
57
+ def self.follows_type?(type, value)
58
+ if type == Question::Type::YESORNO
59
+ return Question::Answer.yes_or_no?(value)
60
+ elsif type == Question::Type::SCALE
61
+ return Question::Answer.scale?(value)
62
+ else
63
+ fail "#{type} is an invalid question type!"
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ # Basic Test Class
70
+ class Test
71
+ # The test's questions plus the type of question they are
72
+ QUESTIONS = [
73
+ ['This is a standard question.', :yn],
74
+ ['This is another question.', :scale]
75
+ ]
76
+
77
+ def initialize
78
+ @answers = []
79
+ end
80
+
81
+ # Enable the use of self.Q<number> for easy implementation of tests
82
+ def method_missing(name, *args)
83
+ section = name[1..(name.length - 1)]
84
+ if name[0] == 'Q' && self.out_of_index?(section.to_i - 1)
85
+ return @answers[section.to_i - 1]
86
+ else
87
+ super
88
+ end
89
+ end
90
+
91
+ # Check for out of index
92
+ def out_of_index?(index, truism = false)
93
+ if (index) > (self.class.const_get(:QUESTIONS).length - 1)
94
+ if truism
95
+ false
96
+ else
97
+ fail "##{index} Out of Index"
98
+ end
99
+ end
100
+ true
101
+ end
102
+
103
+ # Get question via index
104
+ def get_question(index)
105
+ self.out_of_index? index
106
+ self.class.const_get(:QUESTIONS)[index].dup
107
+ end
108
+
109
+ # Alias get_question
110
+ def question(*args)
111
+ get_question(*args)
112
+ end
113
+
114
+ # Set question answer to value
115
+ def set_answer(index, value)
116
+ self.out_of_index? index
117
+ type = self.class.const_get(:QUESTIONS)[index][1]
118
+
119
+ unless Question::Answer.follows_type?(type, value)
120
+ fail "Type doesn't match with question type!"
121
+ end
122
+ @answers[index] = value
123
+ end
124
+
125
+ # Alias set_answer
126
+ def answer(*args)
127
+ set_answer(*args)
128
+ end
129
+
130
+ # Alias set_answer
131
+ def answer=(args)
132
+ set_answer(*args)
133
+ end
134
+
135
+ # Get a list of the answers so far
136
+ def answers
137
+ Marshal.load(Marshal.dump(@answers))
138
+ end
139
+
140
+ # Done supplying answers to questions?
141
+ def finished?
142
+ if @answers.length >= self.class.const_get(:QUESTIONS).length
143
+ return true
144
+ else
145
+ return false
146
+ end
147
+ end
148
+
149
+ # Alias finished?
150
+ def done?
151
+ self.finished?
152
+ end
153
+
154
+ # Stub method for result of test
155
+ def result
156
+ fail 'Not ready yet!' unless self.finished?
157
+ @answers.to_s
158
+ end
159
+ end
160
+
161
+ # Basic Scale5 Test Class
162
+ class ScaleTest < Test
163
+ # Default scale questions
164
+ QUESTIONS = ['very not dead|very dead', 'very not alive|very alive']
165
+
166
+ # Set question answer to value
167
+ def set_answer(index, value)
168
+ self.out_of_index? index
169
+ fail "#{value} is not a scale!" unless Question::Answer.scale?(value)
170
+ @answers[index] = value
171
+ end
172
+
173
+ # Randomize the answers to a scale test
174
+ def randomize!
175
+ self.class.const_get(:QUESTIONS).length.times do |num|
176
+ set_answer(num, rand(1..5))
177
+ end
178
+ nil
179
+ end
180
+
181
+ # Default results for scale test
182
+ def result
183
+ fail 'Not ready yet!' unless self.finished?
184
+ val = @answers[1] - @answers[0]
185
+ if val < 0
186
+ "Sad to hear you're dead."
187
+ elsif val > 0
188
+ "Good to hear you're alive!"
189
+ else
190
+ "You're hard to figure out."
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,105 @@
1
+ # JungI - A simple program for taking open source personality tests.
2
+ # Copyright (C) 2015 Mfrogy Starmade
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ begin
18
+ require_relative './classes'
19
+ rescue LoadError
20
+ require 'jungi/classes'
21
+ end
22
+
23
+ # JungiCli utility module
24
+ module JungiCli
25
+ # Fetch terminal width
26
+ def self.width
27
+ val = `tput cols`.chomp.to_i
28
+ val = 80 if val == 0
29
+ val
30
+ rescue Errno::ENOENT
31
+ 80
32
+ end
33
+
34
+ # Fetch prototype objects
35
+ def self.scale_proto
36
+ start = (' |1|2|3|4|5| '.center width)
37
+ start.partition(' |1|2|3|4|5| ')
38
+ end
39
+
40
+ # Handle question via scale
41
+ def self.parse_scale(scale)
42
+ p1, p2 = scale.split '|'
43
+ if p2
44
+ s1, c1, s2 = scale_proto
45
+ s1[s1.length - p1.length, s1.length - 1] = p1
46
+ s2[0, p2.length - 1] = p2
47
+ s1 + c1 + s2
48
+ else
49
+ (p1 + ' |1|2|3|4|5| ').center WIDTH
50
+ end
51
+ end
52
+
53
+ # Ask for integer
54
+ def self.ask_integer(prompt)
55
+ result = nil
56
+ until yield result
57
+ print prompt
58
+ result = gets.chomp.to_i
59
+ end
60
+ result
61
+ end
62
+
63
+ # Nicely ask a scale
64
+ def self.ask_scale(scale, randomize = false)
65
+ puts parse_scale scale
66
+
67
+ if randomize
68
+ int = rand(1..5)
69
+ puts "> #{int}"
70
+ int
71
+
72
+ else
73
+ ask_integer '> ' do |r|
74
+ Question::Answer.scale? r
75
+ end
76
+ end
77
+ end
78
+
79
+ # Pad a document to width
80
+ def self.center_doc(doc)
81
+ doc = doc.split "\n"
82
+ out = []
83
+ doc.length.times do |int|
84
+ out[int] = doc[int].center width
85
+ end
86
+ out
87
+ end
88
+
89
+ # Display document centered
90
+ def self.display_doc(doc)
91
+ center_doc(doc).each do |line|
92
+ puts line
93
+ end
94
+ end
95
+
96
+ # Render line
97
+ def self.line
98
+ puts '-' * width
99
+ end
100
+
101
+ # Clear screen
102
+ def self.clr
103
+ system('clear') || system('cls')
104
+ end
105
+ end
@@ -0,0 +1,170 @@
1
+ # JungI - A simple program for taking open source personality tests.
2
+ # Copyright (C) 2015 Mfrogy Starmade
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ # The items of the Open Extended Jungian Type Scales 1.2 are licenced
18
+ # under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0
19
+ # International License by Eric Jorgenson. The OEJTS comes with no
20
+ # guarantees of reliability or accuracy of any kind.
21
+ #
22
+ # https://creativecommons.org/licenses/by-nc-sa/4.0/
23
+
24
+ begin
25
+ require_relative './classes'
26
+ rescue LoadError
27
+ require 'jungi/classes'
28
+ end
29
+
30
+ # Implementation of OEJTS
31
+ class OEJTSTest < ScaleTest
32
+ DOC = <<END_FILE
33
+ Open Extended Jungian Type Scales 1.2
34
+
35
+ In this test there are 32 pairs of personality descriptions
36
+ connected by a five point scale. For each pair, you must
37
+ choose where on the scale between them you think you are.
38
+ For example, if the pair is "angry” versus “calm”,
39
+ you should type in a 1 if you are always angry and never
40
+ calm, a 3 if you are half and half, etc. Press <ENTER>
41
+ after typing your answer. Answer honestly and as you are,
42
+ not as you hope to be.
43
+ END_FILE
44
+ QUESTIONS = [
45
+ 'makes lists|relies on memory',
46
+ 'sceptical|wants to believe',
47
+ 'bored by time alone|needs time alone',
48
+ 'accepts things as they are|unsatisfied with the way things are',
49
+ 'keeps a clean room|just puts stuff where ever',
50
+ "thinks \"robotic\" is an insult|strives to have a mechanical mind",
51
+ 'energetic|mellow',
52
+ 'prefer to take multiple choice test|prefer essay answers',
53
+ 'chaotic|organized',
54
+ 'easily hurt|thick-skinned',
55
+ 'works best in groups|works best alone',
56
+ 'focused on the past|focused on the future',
57
+ 'plans far ahead|plans at the last minute',
58
+ "wants people's respect|wants their love",
59
+ 'gets worn out by parties|gets fired up by parties',
60
+ 'fits in|stands out',
61
+ 'keeps options open|commits',
62
+ 'wants to be good at fixing things|wants to be good at fixing people',
63
+ 'talks more|listens more',
64
+ 'when describing an event, will tell people what happened|when descr'\
65
+ 'ibing an event, will tell people what it meant',
66
+ 'gets work done right away|procrastinates',
67
+ 'follows the heart|follows the head',
68
+ 'stays at home|goest out on the town',
69
+ 'wants the big picture|wants the details',
70
+ 'improvises|prepares',
71
+ 'bases morality on justice|bases morality on compassion',
72
+ 'finds it difficult to yell very loudly|yelling to others when they are'\
73
+ ' far away comes naturally',
74
+ 'theoretical|empirical',
75
+ 'works hard|plays hard',
76
+ 'uncomfortable with emotions|values emotions',
77
+ 'likes to perform in front of other people|avoids public speaking',
78
+ "likes to know \"who?\", \"what?\", \"when?\"|likes to know \"why?\""
79
+ ]
80
+
81
+ def result
82
+ fail 'Not ready yet!' unless self.finished?
83
+ ie = 30 - self.Q3 - self.Q7 - self.Q11 + self.Q15 -
84
+ self.Q19 + self.Q23 + self.Q27 - self.Q31
85
+ sn = 12 + self.Q4 + self.Q8 + self.Q12 + self.Q16 +
86
+ self.Q20 - self.Q24 - self.Q28 + self.Q32
87
+ ft = 30 - self.Q2 + self.Q6 + self.Q10 - self.Q14 -
88
+ self.Q18 + self.Q22 - self.Q26 - self.Q30
89
+ jp = 18 + self.Q1 + self.Q5 - self.Q9 + self.Q13 -
90
+ self.Q17 + self.Q21 - self.Q25 + self.Q29
91
+ desig = ''
92
+
93
+ if ie > 24
94
+ desig << 'E'
95
+ else
96
+ desig << 'I'
97
+ end
98
+ if sn > 24
99
+ desig << 'N'
100
+ else
101
+ desig << 'S'
102
+ end
103
+ if ft > 24
104
+ desig << 'T'
105
+ else
106
+ desig << 'F'
107
+ end
108
+ if jp > 24
109
+ desig << 'P'
110
+ else
111
+ desig << 'J'
112
+ end
113
+
114
+ iev = (ie - 24).abs
115
+ snv = (sn - 24).abs
116
+ ftv = (ft - 24).abs
117
+ jpv = (jp - 24).abs
118
+
119
+ [desig, iev, snv, ftv, jpv]
120
+ end
121
+
122
+ def self.parse_iev(desig, iev)
123
+ word = desig[0] == 'E' ? 'Extraversion' : 'Intraversion'
124
+ if iev.between?(0, 1)
125
+ "Lukewarm #{word}, "
126
+ elsif iev < 4
127
+ "Weak(#{iev}) #{word}, "
128
+ else
129
+ "Strong(#{iev}) #{word}, "
130
+ end
131
+ end
132
+
133
+ def self.parse_snv(desig, snv)
134
+ word = desig[1] == 'S' ? 'Sensing' : 'Intuition'
135
+ if snv.between?(0, 1)
136
+ "Lukewarm #{word}\n"
137
+ elsif snv < 4
138
+ "Weak(#{snv}) #{word}\n"
139
+ else
140
+ "Strong(#{snv}) #{word}\n"
141
+ end
142
+ end
143
+
144
+ def self.parse_ftv(desig, ftv)
145
+ word = desig[2] == 'F' ? 'Feeling' : 'Thinking'
146
+ if ftv.between?(0, 1)
147
+ "Lukewarm #{word}, "
148
+ elsif ftv < 4
149
+ "Weak(#{ftv}) #{word} "
150
+ else
151
+ "Strong(#{ftv}) #{word}, "
152
+ end
153
+ end
154
+
155
+ def self.parse_jpv(desig, jpv)
156
+ word = desig[3] == 'J' ? 'Judging' : 'Perceiving'
157
+ if jpv.between?(0, 1)
158
+ "Lukewarm #{word}"
159
+ elsif jpv < 4
160
+ "Weak(#{jpv}) #{word}"
161
+ else
162
+ "Strong(#{jpv}) #{word}"
163
+ end
164
+ end
165
+
166
+ def self.parse_result(desig, iev, snv, ftv, jpv)
167
+ parse_iev(desig, iev) << parse_snv(desig, snv) <<
168
+ parse_ftv(desig, ftv) << parse_jpv(desig, jpv)
169
+ end
170
+ end