profilepic 0.1.4 → 0.1.5
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.
- checksums.yaml +4 -4
- data/Manifest.txt +7 -7
- data/README.md +35 -2
- data/lib/profilepic/builder.rb +55 -99
- data/lib/profilepic/config/doge.rb +52 -0
- data/lib/profilepic/config/marcs.rb +163 -0
- data/lib/profilepic/config/saudis.rb +106 -0
- data/lib/profilepic/config/yeoldepunks.rb +204 -0
- data/lib/profilepic/helper.rb +162 -0
- data/lib/profilepic/public/spritesheet.js +7 -2
- data/lib/profilepic/public/style.css +19 -0
- data/lib/profilepic/service.rb +204 -417
- data/lib/profilepic/version.rb +1 -1
- data/lib/profilepic/views/doge.erb +5 -47
- data/lib/profilepic/views/index.erb +40 -13
- data/lib/profilepic/views/layout.erb +1 -1
- data/lib/profilepic/views/marcs.erb +5 -190
- data/lib/profilepic/views/more.erb +84 -0
- data/lib/profilepic/views/saudis.erb +33 -0
- data/lib/profilepic/views/yeoldepunks.erb +5 -202
- data/lib/profilepic.rb +9 -3
- metadata +9 -9
- data/lib/profilepic/public/doge-24x24.csv +0 -23
- data/lib/profilepic/public/doge-24x24.png +0 -0
- data/lib/profilepic/public/marcs-24x24.csv +0 -149
- data/lib/profilepic/public/marcs-24x24.png +0 -0
- data/lib/profilepic/public/yeoldepunks-24x24.csv +0 -134
- data/lib/profilepic/public/yeoldepunks-24x24.png +0 -0
- data/lib/profilepic/views/shared/_more_options.erb +0 -49
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
YEOLDEPUNK = {
|
|
5
|
+
t: {
|
|
6
|
+
legend: "Select a ye olde' punk base (archetype)",
|
|
7
|
+
options: [
|
|
8
|
+
'Male 1',
|
|
9
|
+
'Male 2',
|
|
10
|
+
'Male 3',
|
|
11
|
+
'Male 4',
|
|
12
|
+
'Female 1',
|
|
13
|
+
'Female 2',
|
|
14
|
+
'Female 3',
|
|
15
|
+
'Female 4',
|
|
16
|
+
'Zombie',
|
|
17
|
+
'Ape',
|
|
18
|
+
'Alien',
|
|
19
|
+
'Bot',
|
|
20
|
+
'Zombie Female',
|
|
21
|
+
'Ape Female',
|
|
22
|
+
'Alien Female',
|
|
23
|
+
'Bot Female',
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
cheeks: {
|
|
29
|
+
legend: 'Select cheeks',
|
|
30
|
+
none: true,
|
|
31
|
+
options: [
|
|
32
|
+
'Rosy Cheeks (m/f)',
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
blemish: {
|
|
37
|
+
legend: 'Select blemish',
|
|
38
|
+
none: true,
|
|
39
|
+
options: [
|
|
40
|
+
'Mole (m/f)',
|
|
41
|
+
'Spots (m/f)',
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
hair: {
|
|
46
|
+
legend: 'Select hair',
|
|
47
|
+
none: true, ## check - use/rename to required/optional - why? why not?
|
|
48
|
+
options: [
|
|
49
|
+
'Shaved Head (m/f)',
|
|
50
|
+
'Peak Spike (m/f)',
|
|
51
|
+
'Vampire Hair (m/f)',
|
|
52
|
+
'Purple Hair (m/f)',
|
|
53
|
+
|
|
54
|
+
'Mohawk (m/f)',
|
|
55
|
+
'Mohawk Dark (m/f)',
|
|
56
|
+
'Mohawk Thin (m/f)',
|
|
57
|
+
'Wild Hair (m/f)',
|
|
58
|
+
'Crazy Hair (m/f)',
|
|
59
|
+
'Messy Hair (m/f)',
|
|
60
|
+
'Frumpy Hair (m/f)',
|
|
61
|
+
'Stringy Hair (m/f)',
|
|
62
|
+
'Clown Hair Green (m/f)',
|
|
63
|
+
|
|
64
|
+
'Straight Hair (m/f)',
|
|
65
|
+
'Straight Hair Dark (m/f)',
|
|
66
|
+
'Straight Hair Blonde (m/f)',
|
|
67
|
+
'Blonde Short (m/f)',
|
|
68
|
+
'Blonde Bob (m/f)',
|
|
69
|
+
'Wild Blonde (m/f)',
|
|
70
|
+
'Wild White Hair (m/f)',
|
|
71
|
+
'Orange Side (m/f)',
|
|
72
|
+
'Dark Hair (m/f)',
|
|
73
|
+
'Pigtails (m/f)',
|
|
74
|
+
'Pink With Hat¹ (m/f)',
|
|
75
|
+
'Half Shaved (m/f)',
|
|
76
|
+
'Red Mohawk (m/f)',
|
|
77
|
+
],
|
|
78
|
+
notes: "¹: Note: Pink With Hat is a hair+headwear combo.",
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
beard: {
|
|
82
|
+
legend: 'Select beard',
|
|
83
|
+
none: true,
|
|
84
|
+
options: [
|
|
85
|
+
'Shadow Beard (m)',
|
|
86
|
+
'Normal Beard (m)',
|
|
87
|
+
'Normal Beard Black (m)',
|
|
88
|
+
'Big Beard (m)',
|
|
89
|
+
'Luxurious Beard (m)',
|
|
90
|
+
'Mustache (m)',
|
|
91
|
+
'Goat (m)',
|
|
92
|
+
'Handlebars (m)',
|
|
93
|
+
'Front Beard (m)',
|
|
94
|
+
'Front Beard Dark (m)',
|
|
95
|
+
'Chinstrap (m)',
|
|
96
|
+
'Muttonchops (m)',
|
|
97
|
+
],
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
eyes: {
|
|
101
|
+
legend: 'Select eyes (make-up)',
|
|
102
|
+
none: true,
|
|
103
|
+
options: [
|
|
104
|
+
'Clown Eyes Green (m/f)',
|
|
105
|
+
'Clown Eyes Blue (m/f)',
|
|
106
|
+
'Green Eye Shadow (f)',
|
|
107
|
+
'Blue Eye Shadow (f)',
|
|
108
|
+
'Purple Eye Shadow (f)',
|
|
109
|
+
]
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
eyewear: {
|
|
113
|
+
legend: 'Select eyewear',
|
|
114
|
+
none: true,
|
|
115
|
+
options: [
|
|
116
|
+
'Small Shades (m/f)',
|
|
117
|
+
'Regular Shades (m/f)',
|
|
118
|
+
'Classic Shades (m/f)',
|
|
119
|
+
'Big Shades (m/f)',
|
|
120
|
+
'Nerd Glasses (m/f)',
|
|
121
|
+
'Horned Rim Glasses (m/f)',
|
|
122
|
+
'3D Glasses (m/f)',
|
|
123
|
+
'VR (m/f)',
|
|
124
|
+
'Eye Mask (m/f)',
|
|
125
|
+
'Eye Patch (m/f)',
|
|
126
|
+
'Welding Goggles (m/f)',
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
nose: {
|
|
131
|
+
legend: 'Select nose accessory',
|
|
132
|
+
none: true,
|
|
133
|
+
options: [
|
|
134
|
+
'Clown Nose (m/f)',
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
mouth: {
|
|
139
|
+
legend: 'Select mouth expression / lipstick make-up',
|
|
140
|
+
none: true,
|
|
141
|
+
options: [
|
|
142
|
+
'Smile (m)',
|
|
143
|
+
'Frown (m)',
|
|
144
|
+
'Buck Teeth (m)',
|
|
145
|
+
'Hot Lipstick (f)',
|
|
146
|
+
'Black Lipstick (f)',
|
|
147
|
+
'Purple Lipstick (f)',
|
|
148
|
+
]
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
mouthprop: {
|
|
152
|
+
legend: 'Select mouth prop',
|
|
153
|
+
none: true,
|
|
154
|
+
options: [
|
|
155
|
+
'Cigarette (m/f)',
|
|
156
|
+
'Vape (m/f)',
|
|
157
|
+
'Pipe (m/f)',
|
|
158
|
+
'Medical Mask (m/f)',
|
|
159
|
+
]
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
earring: {
|
|
163
|
+
legend: 'Select earring',
|
|
164
|
+
none: true,
|
|
165
|
+
options: [
|
|
166
|
+
'Earring (m/f)'
|
|
167
|
+
]
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
headwear: {
|
|
171
|
+
legend: 'Select headwear',
|
|
172
|
+
none: true,
|
|
173
|
+
options: [
|
|
174
|
+
'Cowboy Hat (m/f)',
|
|
175
|
+
'Fedora (m/f)',
|
|
176
|
+
'Hoodie (m/f)',
|
|
177
|
+
'Beanie (m/f)',
|
|
178
|
+
'Top Hat (m/f)',
|
|
179
|
+
'Do-rag (m/f)',
|
|
180
|
+
'Police Cap (m/f)',
|
|
181
|
+
'Cap Forward (m/f)',
|
|
182
|
+
'Cap (m/f)',
|
|
183
|
+
'Knitted Cap (m/f)',
|
|
184
|
+
'Bandana (m/f)',
|
|
185
|
+
'Headband¹ (m/f)',
|
|
186
|
+
'Pilot Helmet (m/f)',
|
|
187
|
+
'Tassle Hat (m/f)',
|
|
188
|
+
'Tiara (m/f)',
|
|
189
|
+
],
|
|
190
|
+
notes: '¹: Note: Headband (f) is a (black) hair+headwear combo.',
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
neck: {
|
|
194
|
+
legend: 'Select neck accessory',
|
|
195
|
+
none: true,
|
|
196
|
+
options: [
|
|
197
|
+
'Silver Chain (m/f)',
|
|
198
|
+
'Gold Chain (m/f)',
|
|
199
|
+
'Choker (m/f)',
|
|
200
|
+
]
|
|
201
|
+
},
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
################
|
|
2
|
+
# (view) helpers
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def spritesheet( basename ) ## spritesheet metadata / record helpers
|
|
6
|
+
## note: map "virtual name" to local real path
|
|
7
|
+
path = FILES[ basename ]
|
|
8
|
+
recs = read_csv( path )
|
|
9
|
+
|
|
10
|
+
###
|
|
11
|
+
# id, category, name, more_names
|
|
12
|
+
# 0, , classic,
|
|
13
|
+
# 1, , dark,
|
|
14
|
+
# 2, , zombie,
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# id, name, gender, size, type, more_names
|
|
18
|
+
# 0, Male 1, m, l, Archetype,
|
|
19
|
+
# 1, Male 2, m, l, Archetype,
|
|
20
|
+
# 2, Male 3, m, l, Archetype,
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
buf = String.new('')
|
|
24
|
+
recs.each do |rec|
|
|
25
|
+
id = rec['id']
|
|
26
|
+
name = rec['name']
|
|
27
|
+
more_names = (rec['more_names'] || '').split( '|' )
|
|
28
|
+
|
|
29
|
+
names = [name]
|
|
30
|
+
names += more_names
|
|
31
|
+
|
|
32
|
+
if rec.has_key?( 'gender' )
|
|
33
|
+
archetype = (rec['type'] || rec['category'] || '').downcase.strip == 'archetype'
|
|
34
|
+
if archetype
|
|
35
|
+
## do nothing for base archetype (e.g. male 1, alien, etc.)
|
|
36
|
+
else
|
|
37
|
+
## auto-add qualifer e.g. (m) or (f) via gender
|
|
38
|
+
gender = (rec['gender'] || 'm').downcase.strip
|
|
39
|
+
names = names.map { |name| "#{name} (#{gender})"}
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
buf << "#{id}, #{names.join(' | ')}\n"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
buf
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def render_options( spec )
|
|
54
|
+
|
|
55
|
+
buf = String.new('')
|
|
56
|
+
|
|
57
|
+
spec.each do |name, h|
|
|
58
|
+
|
|
59
|
+
options = h[:options]
|
|
60
|
+
options = ['None'] + options if h[:none]
|
|
61
|
+
|
|
62
|
+
legend = h[:legend]
|
|
63
|
+
|
|
64
|
+
buf += radio_options_w_sprites( options,
|
|
65
|
+
name: name,
|
|
66
|
+
legend: legend )
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
buf += "\n#{h[:notes]}\n\n" if h[:notes]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
buf
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def radio_button_tag( name, value, checked: false, id: )
|
|
79
|
+
buf = %Q[ <input type="radio" id="#{id}" name="#{name}" value="#{value}" ]
|
|
80
|
+
buf += " checked " if checked
|
|
81
|
+
buf += ">\n"
|
|
82
|
+
buf
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def label_tag( content, id: )
|
|
86
|
+
%Q[ <label for="#{id}">#{content}</label>\n]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def sprite_tag( name )
|
|
90
|
+
%Q[ <span class="sprite" data-name="#{name}"></span>\n]
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def radio_options_w_sprites( options, name:, legend: )
|
|
97
|
+
radio_options( options, name: name,
|
|
98
|
+
legend: legend,
|
|
99
|
+
sprites: true )
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def radio_options( options, name:,
|
|
104
|
+
legend:,
|
|
105
|
+
sprites: false )
|
|
106
|
+
|
|
107
|
+
buf = <<TXT
|
|
108
|
+
<fieldset>
|
|
109
|
+
<legend>#{legend}:</legend>
|
|
110
|
+
TXT
|
|
111
|
+
|
|
112
|
+
options.each_with_index do |option,i|
|
|
113
|
+
|
|
114
|
+
value = option.downcase
|
|
115
|
+
|
|
116
|
+
## auto-extract qualifiers e.g. (m)ale/(f)emale
|
|
117
|
+
qualifiers = if value.index( '(m)' ) then ['m']
|
|
118
|
+
elsif value.index( '(f)' ) then ['f']
|
|
119
|
+
elsif value.index( '(m/f)' ) then ['m', 'f']
|
|
120
|
+
else []
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
value = value.sub( '(m)', '' ).sub( '(f)', '' ).sub( '(m/f)', '' ).sub( '¹', '' )
|
|
124
|
+
value = value.strip
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
label = option
|
|
128
|
+
id = "#{name}#{i}" ## use for input (dom) id / label for [id]
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
## note. add class columns - via css turns div into 250px inline-blocks
|
|
132
|
+
buf += "<div class='columns'>\n"
|
|
133
|
+
buf += radio_button_tag( name, value,
|
|
134
|
+
id: id,
|
|
135
|
+
checked: i==0 )
|
|
136
|
+
|
|
137
|
+
buf2 = String.new( '' )
|
|
138
|
+
if sprites
|
|
139
|
+
if ['none'].include?( value )
|
|
140
|
+
## do nothing - no sprite(s) - for none & friends
|
|
141
|
+
elsif qualifiers.empty?
|
|
142
|
+
buf2 += sprite_tag( value )
|
|
143
|
+
else
|
|
144
|
+
qualifiers.each do |qualifier|
|
|
145
|
+
buf2 += sprite_tag( "#{value} (#{qualifier})" )
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
## note: add sprites (spans) inside label e.g. <label> HERE </label>
|
|
149
|
+
buf += label_tag( buf2 + label, id: id )
|
|
150
|
+
else
|
|
151
|
+
buf += label_tag( label, id: id )
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
buf += "</div>\n"
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
buf += "</fieldset>\n"
|
|
159
|
+
buf
|
|
160
|
+
|
|
161
|
+
end
|
|
162
|
+
|
|
@@ -51,9 +51,14 @@ class Spritesheet {
|
|
|
51
51
|
let names = {};
|
|
52
52
|
for( let row of rows ) {
|
|
53
53
|
let id = parseInt( row[0] );
|
|
54
|
-
let name = this._norm_name( row[1] );
|
|
55
54
|
|
|
56
|
-
|
|
55
|
+
// note: allow more than one name (split by pipe e.g. |)
|
|
56
|
+
// Marc 2 | Marc Mid | Marc Medium
|
|
57
|
+
let values = row[1].split('|');
|
|
58
|
+
for( let name of values) {
|
|
59
|
+
name = this._norm_name( name );
|
|
60
|
+
names[ name ] = id;
|
|
61
|
+
}
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
return names;
|
|
@@ -15,6 +15,25 @@ body {
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
fieldset div.columns {
|
|
19
|
+
display: inline-block;
|
|
20
|
+
width: 240px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
fieldset {
|
|
24
|
+
background-color: floralwhite;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
button.bigblue {
|
|
29
|
+
font-size: 400%;
|
|
30
|
+
color: white;
|
|
31
|
+
background-color: blue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
18
37
|
|
|
19
38
|
/** version block **********/
|
|
20
39
|
|