Преглед на файлове

Improve card generation code

crobi преди 10 години
родител
ревизия
287b6b0534
променени са 4 файла, в които са добавени 218 реда и са изтрити 136 реда
  1. 3
    7
      generator/css/cards.css
  2. 14
    14
      generator/data/card_data_example.js
  3. 199
    114
      generator/js/cards.js
  4. 2
    1
      generator/js/control.js

+ 3
- 7
generator/css/cards.css Целия файл

@@ -22,6 +22,7 @@
22 22
     border-radius: 2mm;
23 23
     margin-top:0px;
24 24
     background-color: white;
25
+    border-color: inherit;
25 26
     display: flex;
26 27
     flex-direction: column;
27 28
     flex: 1;
@@ -117,6 +118,7 @@ h3 {
117 118
     letter-spacing: 1px;
118 119
     margin: 0;
119 120
     margin-bottom: 0.3em;
121
+    border-color: inherit;
120 122
 }
121 123
 
122 124
 p {
@@ -124,13 +126,7 @@ p {
124 126
     margin-bottom: 0.5em;
125 127
 }
126 128
 
127
-
128
-.fill-1 {flex:1;}
129
-.fill-2 {flex:2;}
130
-.fill-3 {flex:3;}
131
-.fill-4 {flex:4;}
132
-.fill-5 {flex:5;}
133
-.fill-6 {flex:6;}
129
+.fill {flex:1;}
134 130
 
135 131
 .description-line {
136 132
     margin-bottom: 0.5em;

+ 14
- 14
generator/data/card_data_example.js Целия файл

@@ -12,10 +12,10 @@ var card_data = [
12 12
             "property | Range | Self (15ft cone)",
13 13
             "property | Components | V,S",
14 14
             "rule",
15
-            "fill-2",
15
+            "fill | 2",
16 16
             "text | Each creature in a 15-foot cone must make a Dexterity saving throw. A creature takes <b>3d6 fire damage</b> on a failed save, or half as much damage on a successful one.",
17 17
             "text | The fire ignites any flammable objects in the area that aren’t being worn or carried.",
18
-            "fill-3",
18
+            "fill | 3",
19 19
             "section | At higher levels",
20 20
             "text | +1d6 damage for each slot above 1st"
21 21
         ]
@@ -29,9 +29,9 @@ var card_data = [
29 29
         "contents": [
30 30
             "subtitle | Rogue feature",
31 31
             "rule",
32
-            "fill-2",
32
+            "fill | 2",
33 33
             "text | You can take a <b>bonus action on each of your turns</b> in combat. This action can be used only to take the <b>Dash, Disengage, or Hide</b> action.",
34
-            "fill-3",
34
+            "fill | 2",
35 35
             "section | Fast hands (Thief 3rd)",
36 36
             "text | You can also use the bonus action to make a Dexterity (<b>Sleight of Hand</b>) check, use your thieves’ tools to <b>disarm a trap</b> or <b>open a lock</b>, or take the <b>Use an Object</b> action.",
37 37
         ]
@@ -48,10 +48,10 @@ var card_data = [
48 48
             "property | Strength required | 15",
49 49
             "property | Stealth | Disadvantage",
50 50
             "rule",
51
-            "fill-2",
51
+            "fill | 2",
52 52
             "description | Heavy | Unless you have the required strength, your speed is reduced by 10 feet.",
53 53
             "description | Stealth | You have disadvantage on Dexterity (Stealth) checks.",
54
-            "fill-3"
54
+            "fill | 3"
55 55
         ]
56 56
     },
57 57
     {
@@ -66,11 +66,11 @@ var card_data = [
66 66
             "property | Modifier | Strength or Dexterity",
67 67
             "property | Properties | Light, Finesse, Thrown (20/60)",
68 68
             "rule",
69
-            "fill-2",
69
+            "fill | 2",
70 70
             "description | Finesse | Use your choice of Strength or Dexterity modifier for attack and damage.",
71 71
             "description | Light | When you attack while dual wielding light weapons, you may use a bonus action to attack with your off hand.",
72 72
             "description | Thrown | You can throw the weapon to make a ranged attack with the given range.",
73
-            "fill-3"
73
+            "fill | 3"
74 74
         ]
75 75
     },
76 76
     {
@@ -85,10 +85,10 @@ var card_data = [
85 85
             "property | Modifier | Strength or Dexterity",
86 86
             "property | Properties | Light, Finesse",
87 87
             "rule",
88
-            "fill-2",
88
+            "fill | 2",
89 89
             "description | Finesse | Use your choice of Strength or Dexterity modifier for attack and damage.",
90 90
             "description | Light | When you attack while dual wielding light weapons, you may use a bonus action to attack with your off hand.",
91
-            "fill-3"
91
+            "fill | 3"
92 92
         ]
93 93
     },
94 94
     {
@@ -103,12 +103,12 @@ var card_data = [
103 103
             "property | Recharge | 1d6+1 each day",
104 104
             "property | Depletion | If you expend the last charge, roll a d20. On a 1, the item is destroyed.",
105 105
             "rule",
106
-            "fill-2",
106
+            "fill | 2",
107 107
             "description | Spells | You can use your action to cast the following spells:",
108 108
             "text | - magic missile, 1st level (1 charge)",
109 109
             "text | - magic missile, 2nd level (2 charges)",
110 110
             "text | - magic missile, 3rd level (3 charges)",
111
-            "fill-3"
111
+            "fill | 3"
112 112
         ]
113 113
     },
114 114
     {
@@ -122,10 +122,10 @@ var card_data = [
122 122
             "property | Use time | 1 action",
123 123
             "property | Hit points restored | 2d4+2",
124 124
             "rule",
125
-            "fill-2",
125
+            "fill | 2",
126 126
             "text | When you drink this potion, you regain 2d4+2 hitpoints.",
127 127
             "text | Drinking or administering a potion takes 1 action.",
128
-            "fill-3"
128
+            "fill | 3"
129 129
         ]
130 130
     }
131 131
 ];

+ 199
- 114
generator/js/cards.js Целия файл

@@ -1,119 +1,172 @@
1
-function card_title(text) {
2
-    return '<div class="title">' + text + '</div>';
1
+// ============================================================================
2
+// Card element generating functions
3
+// ============================================================================
4
+
5
+function card_element_title(card_data) {
6
+    var title = card_data.title || "";
7
+    return '<div class="title">' + title + '</div>';
8
+}
9
+
10
+function card_element_icon(card_data) {
11
+    var icon = card_data.icon_front || card_data.icon;
12
+    var result = "";
13
+    if (icon) {
14
+        result += '<div class="title-icon-container">';
15
+        result += '    <div class="title-icon icon-' + icon + '">';
16
+        result += '    </div>';
17
+        result += '</div>';
18
+    }
19
+    return result;
3 20
 }
4 21
 
5
-function card_subtitle(text) {
6
-    return '<div class="subtitle">' + text + '</div>';
22
+function card_element_subtitle(params, card_data) {
23
+    var subtitle = params[0] || "";
24
+    return '<div class="subtitle">' + subtitle + '</div>';
7 25
 }
8 26
 
9
-function card_ruler() {
27
+function card_element_ruler(params, card_data) {
10 28
     return '<div class="ruler"></div>';
11 29
 }
12 30
 
13
-function card_property(name, text) {
31
+function card_element_property(params, card_data) {
14 32
     var result = "";
15 33
     result += '<div class="property-line">';
16
-    result += '   <h4 class="property-name">' + name.trim() + '</h4>';
17
-    result += '   <p class="property-text">' + text.trim() + '</p>';
34
+    result += '   <h4 class="property-name">' + params[0] + '</h4>';
35
+    result += '   <p class="property-text">' + params[1] + '</p>';
18 36
     result += '</div>';
19 37
     return result;
20 38
 }
21 39
 
22
-function card_description(name, text) {
40
+function card_element_description(params, card_data) {
23 41
     var result = "";
24 42
     result += '<div class="description-line">';
25
-    result += '   <h4 class="description-name">' + name.trim() + '</h4>';
26
-    result += '   <p class="description-text">' + text.trim() + '</p>';
43
+    result += '   <h4 class="description-name">' + params[0] + '</h4>';
44
+    result += '   <p class="description-text">' + params[1] + '</p>';
27 45
     result += '</div>';
28 46
     return result;
29 47
 }
30 48
 
31
-function card_section(text) {
32
-    return '<h3>'+text+'</h3>';
49
+function card_element_text(params, card_data) {
50
+    var result = "";
51
+    result += '<div class="description-line">';
52
+    result += '   <p class="description-text">' + params[0] + '</p>';
53
+    result += '</div>';
54
+    return result;
33 55
 }
34 56
 
35
-function card_fill1() {
36
-    return '<div class="fill-1"></div>';
57
+function card_element_section(params, card_data) {
58
+    var color = card_data.color_front || card_data.color;
59
+    var section = params[0] || "";
60
+    return '<h3 style="color:' + color + '">' + section + '</h3>';
37 61
 }
38
-function card_fill2() {
39
-    return '<div class="fill-2"></div>';
40
-}
41
-function card_fill3() {
42
-    return '<div class="fill-3"></div>';
43
-}
44
-function card_fill4() {
45
-    return '<div class="fill-4"></div>';
62
+
63
+function card_element_fill(params, card_data) {
64
+    var flex = params[0] || "1";
65
+    return '<div class="fill" style="flex:' + flex + '"></div>';
46 66
 }
47 67
 
48
-function card_icon(name) {
49
-    var result = "";
50
-    result += '<div class="title-icon-container">';
51
-    result += '    <div class="title-icon icon-' + name + '">';
52
-    result += '    </div>';
53
-    result += '</div>';
54
-    return result;
68
+function card_element_unknown(params, card_data) {
69
+    return '<div>' + params.join('<br />') + '</div>';
55 70
 }
56 71
 
57
-function card_contents(contents) {
72
+var card_element_generators = {
73
+    subtitle: card_element_subtitle,
74
+    property: card_element_property,
75
+    rule: card_element_ruler,
76
+    description: card_element_description,
77
+    text: card_element_text,
78
+    fill: card_element_fill
79
+};
80
+
81
+// ============================================================================
82
+// Card generating functions
83
+// ============================================================================
84
+
85
+function card_generate_contents(contents, card_data) {
58 86
     var result = "";
59 87
     result += '<div class="content-container">';
60 88
     result += contents.map(function (value) {
61 89
         var parts = value.split("|").map(function (str) { return str.trim(); });
62
-        switch (parts[0]) {
63
-            case 'subtitle': return card_subtitle(parts[1], parts[2]); break;
64
-            case 'property': return card_property(parts[1], parts[2]); break;
65
-            case 'rule': return card_ruler(); break;
66
-            case 'description': return card_description(parts[1], parts[2]); break;
67
-            case 'text': return card_description("", parts[1]); break;
68
-            case 'fill-1': return card_fill1(); break;
69
-            case 'fill-2': return card_fill2(); break;
70
-            case 'fill-3': return card_fill3(); break;
71
-            case 'fill-4': return card_fill4(); break;
72
-            case 'section': return card_section(parts[1]); break;
73
-            default: return "";
90
+        var element_name = parts[0];
91
+        var element_params = parts.splice(1);
92
+        var element_generator = card_element_generators[element_name];
93
+        if (element_generator) {
94
+            return element_generator(element_params, card_data);
95
+        } else {
96
+            return card_element_unknown(element_params, card_data);
74 97
         }
75 98
     }).join("\n");
76 99
     result += '</div>';
77 100
     return result;
78 101
 }
79 102
 
80
-var card_default_data = {
81
-    count:1,
82
-    title:"",
83
-    icon:"",
84
-    contents:[],
85
-    color: "white"
103
+function card_repeat(card, count) {
104
+    var result = [];
105
+    for (var i = 0; i < count; ++i) {
106
+        result.push(card);
107
+    }
108
+    return result;
109
+}
110
+
111
+function card_generate_color_style(color) {
112
+    return 'style="color:' + color + '; border-color:' + color + '; background-color:' + color + '"';
86 113
 }
87 114
 
88
-function card(data) {
89
-    var front = "";
90
-    var back = "";
115
+function card_generate_color_gradient_style(color) {
116
+    return 'style="background: radial-gradient(ellipse at center, white 20%, ' + color + ' 120%)"';
117
+}
91 118
 
92
-    front += '<div class="card color-' + data.color + '">';
93
-    front += card_icon(data.icon);
94
-    front += card_title(data.title);
95
-    front += card_contents(data.contents);
96
-    front += '</div>';
119
+function card_generate_front(data) {
120
+    var color = data.color_front || data.color || "black";
121
+    var style_color = card_generate_color_style(color);
122
+    var icon = data.icon_front || data.icon || "";
123
+    var count = data.count || 1;
97 124
 
98
-    var icon_back = data.icon_back || data.icon;
99
-    back += '<div class="card color-' + data.color + '">';
100
-    back += '  <div class="card-back">';
101
-    back += '    <div class="card-back-inner">';
102
-    back += '      <div class="back-icon icon-' + icon_back + '"></div>';
103
-    back += '    </div>';
104
-    back += '  </div>';
105
-    back += '</div>';
125
+    var result = "";
126
+    result += '<div class="card" ' + style_color + '>';
127
+    result += card_element_icon(data);
128
+    result += card_element_title(data);
129
+    result += card_generate_contents(data.contents, data);
130
+    result += '</div>';
106 131
 
132
+    return card_repeat(result, count);
133
+}
134
+
135
+function card_generate_back(data) {
136
+    var color = data.color_back || data.color || "black";
137
+    var style_color = card_generate_color_style(color);
138
+    var style_gradient = card_generate_color_gradient_style(color);
139
+    var icon = data.icon_back || data.icon || "ace";
107 140
     var count = data.count || 1;
108
-    var result = { front: [], back: [] };
109
-    for (var i = 0; i < count; ++i) {
110
-        result.front.push(front);
111
-        result.back.push(back);
112
-    }
113
-    return result;
141
+
142
+    var result = "";
143
+    result += '<div class="card" ' + style_color + '>';
144
+    result += '  <div class="card-back" ' + style_gradient + '>';
145
+    result += '    <div class="card-back-inner">';
146
+    result += '      <div class="back-icon icon-' + icon + '" ' + style_color + '></div>';
147
+    result += '    </div>';
148
+    result += '  </div>';
149
+    result += '</div>';
150
+
151
+    return card_repeat(result, count);
152
+}
153
+
154
+function card_generate_empty(count) {
155
+    var style_color = card_generate_color_style("white");
156
+
157
+    var result = "";
158
+    result += '<div class="card" ' + style_color + '>';
159
+    result += '</div>';
160
+
161
+    return card_repeat(result, count);
114 162
 }
115 163
 
116
-function card_split_pages(data, cards_per_page) {
164
+// ============================================================================
165
+// Functions that generate pages of cards
166
+// ============================================================================
167
+
168
+function card_pages_split(data, rows, cols) {
169
+    var cards_per_page = rows * cols;
117 170
     var result = [];
118 171
     for (var i = 0; i < data.length; i += cards_per_page) {
119 172
         var page = data.slice(i, i + cards_per_page);
@@ -122,56 +175,88 @@ function card_split_pages(data, cards_per_page) {
122 175
     return result;
123 176
 }
124 177
 
125
-function cards_flip_left_right(cards) {
126
-    return [
127
-        cards[2], cards[1], cards[0],
128
-        cards[5], cards[4], cards[3],
129
-        cards[8], cards[7], cards[6]
130
-    ];
178
+function card_pages_merge(front_pages, back_pages) {
179
+    var result = [];
180
+    for (var i = 0; i < front_pages.length; ++i) {
181
+        result.push(front_pages[i]);
182
+        result.push(back_pages[i]);
183
+    }
184
+    return result;
131 185
 }
132 186
 
133
-function card_generate_html(datas) {
134
-    var front = [];
135
-    var back = [];
187
+function cards_pages_flip_left_right(cards, rows, cols) {
188
+    var result = [];
189
+    for (var r = 0; r < rows; ++r) {
190
+        for (var c = 0; c < cols; ++c) {
191
+            var i = r*cols + (cols-1-c);
192
+            result.push(cards[i]);
193
+        }
194
+    }
195
+    return result;
196
+}
136 197
 
137
-    // Generate HTML for each card
138
-    datas.forEach(function (data) {
139
-        var result = card(data);
140
-        front = front.concat(result.front);
141
-        back = back.concat(result.back);
142
-    });
198
+function card_pages_add_padding(cards, rows, cols) {
199
+    var cards_per_page = rows * cols;
200
+    var last_page_cards = cards.length % cards_per_page;
201
+    if (last_page_cards !== 0) {
202
+        return cards.concat(card_generate_empty(cards_per_page - last_page_cards));
203
+    } else {
204
+        return cards;
205
+    }
206
+}
143 207
 
144
-    // Fill the last page with blank cards
145
-    if (front.length % 9 !== 0) {
146
-        var result = card(card_default_data);
147
-        for (var i = front.length % 9; i < 9; ++i) {
148
-            front = front.concat(result.front);
149
-            back = back.concat(result.back);
150
-        }
208
+function card_pages_wrap(pages) {
209
+    var size = "A4";
210
+
211
+    var result = "";
212
+    for (var i = 0; i < pages.length; ++i) {
213
+        result += '<page size="' + size + '">\n';
214
+        result += pages[i].join("\n");
215
+        result += '</page>\n';
151 216
     }
217
+    return result;
218
+}
219
+
220
+function card_pages_generate_html(card_data) {
221
+    var rows = 3;
222
+    var cols = 3;
223
+
224
+    // Generate the HTML for each card
225
+    var front_cards = [];
226
+    var back_cards = [];
227
+    card_data.forEach(function (data) {
228
+        front_cards = front_cards.concat(card_generate_front(data));
229
+        back_cards = back_cards.concat(card_generate_back(data));
230
+    });
231
+
232
+    // Add padding cards so that the last page is full of cards
233
+    front_cards = card_pages_add_padding(front_cards, rows, cols);
234
+    back_cards = card_pages_add_padding(back_cards, rows, cols);
152 235
 
153
-    // Split pages
154
-    front_pages = card_split_pages(front, 9);
155
-    back_pages = card_split_pages(back, 9);
236
+    // Split cards to pages
237
+    var front_pages = card_pages_split(front_cards, rows, cols);
238
+    var back_pages = card_pages_split(back_cards, rows, cols);
239
+
240
+    // Shuffle back cards so that they line up with their corresponding front cards
241
+    back_pages = back_pages.map(function (page) {
242
+        return cards_pages_flip_left_right(page, rows, cols);
243
+    });
244
+
245
+    // Interleave front and back pages so that we can print double-sided
246
+    var pages = card_pages_merge(front_pages, back_pages);
247
+
248
+    // Wrap all pages in a <page> element
249
+    return card_pages_wrap(pages);
250
+}
251
+
252
+function card_pages_insert_into(card_data, container) {
156 253
 
157 254
     // Clear the previous content of the document
158
-    var parent_element = document.getElementsByClassName("container")[0];
159
-    while (parent_element.hasChildNodes()) {
160
-        parent_element.removeChild(parent_element.lastChild);
255
+    while (container.hasChildNodes()) {
256
+        container.removeChild(container.lastChild);
161 257
     }
162 258
 
163
-    // Add generated HTML to the document
164
-    for (var i = 0; i < front_pages.length; ++i) {
165
-        var page = document.createElement("page");
166
-        page.setAttribute("size", "A4");
167
-        page.innerHTML = front_pages[i].join("\n");
168
-        parent_element.appendChild(page);
169
-
170
-        var page = document.createElement("page");
171
-        page.setAttribute("size", "A4");
172
-        page.innerHTML = cards_flip_left_right(back_pages[i]).join("\n");
173
-        parent_element.appendChild(page);
174
-    }
259
+    // Insert the HTML
260
+    var html = card_pages_generate_html(card_data);
261
+    container.innerHTML = html;
175 262
 }
176
-
177
-//card_generate_html(card_data);

+ 2
- 1
generator/js/control.js Целия файл

@@ -7,5 +7,6 @@ input_data.value += JSON.stringify(card_data, null, "  ");
7 7
 
8 8
 input_button.onclick = function () {
9 9
     var card_data = JSON.parse(input_data.value);
10
-    card_generate_html(card_data);
10
+    var container = document.getElementsByClassName("container")[0];
11
+    card_pages_insert_into(card_data, container);
11 12
 }

Loading…
Отказ
Запис