profilepic 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|