File size: 16,525 Bytes
a69d738
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
import random
from relatively_constant_variables import player_engagement_items, story_events, all_idea_lists, existing_game_inspirations, multiplayer_features, list_names
import json
import gradio as gr
import re
import os


def pick_random_items(items, n):
    return random.sample(items, n)

def generate_timeline(events, label):
    timeline = []
    for event in events:
        timeline.append((random.randint(1, 100), label, event))
    return timeline

def create_story(timeline):
    story = []
    for entry in timeline:
        if entry[1] == "Story":
            story.append(f"The hero {entry[2].replace('engageBattle', 'engaged in a fierce battle').replace('solveRiddle', 'solved a complex riddle').replace('exploreLocation', 'explored a mysterious location')}.")
        else:
            story.append(f"The player interacted with {entry[2]}.")
    return " ".join(story)

def generate_story_and_timeline(no_story_timeline_points=10, no_ui_timeline_points=10, num_lists=1, items_per_list=1, include_existing_games=False, include_multiplayer=False): # , no_media_timeline_points=5, include_media=True):
    # Pick 10 random UI items
    random_ui_items = pick_random_items(player_engagement_items, no_ui_timeline_points)
    random_story_items = pick_random_items(story_events, no_story_timeline_points)

    # Generate UI and story timelines
    ui_timeline = generate_timeline(random_ui_items, "UI")
    story_timeline = generate_timeline(random_story_items, "Story")

    # Initialize merged timeline with UI and story timelines
    merged_timeline = ui_timeline + story_timeline
    #no_media_merged_timeline = ui_timeline + story_timeline
    #print(merged_timeline)
    #print(no_media_merged_timeline)

    # Include media-related items if specified
    # if include_media:
    #     media_files = generate_media_file_list(no_media_timeline_points)
    #     #rendered_media = render_media_with_dropdowns(media_files)
    #     media_timeline = generate_timeline(media_files, "Media")
    #     merged_timeline += media_timeline

    # print(merged_timeline)

    # Sort the merged timeline based on the random numbers
    merged_timeline.sort(key=lambda x: x[0])
    # no_media_merged_timeline.sort(key=lambda x: x[0])

    # Create the story
    story = create_story(merged_timeline)

    # Format the timeline for display
    formatted_timeline = "\n".join([f"{entry[0]}: {entry[1]} - {entry[2]}" for entry in merged_timeline])
    # no_media_formatted_timeline = "\n".join([f"{entry[0]}: {entry[1]} - {entry[2]}" for entry in no_media_merged_timeline])

    # game_structure_with_media = generate_game_structures(formatted_timeline) #, game_structure_without_media = generate_game_structures(formatted_timeline, no_media_formatted_timeline)
    game_structure_with_media =  convert_timeline_to_game_structure(formatted_timeline)

    print("simulplay debug - good to here 4")

    suggestions, selected_list_names = timeline_get_random_suggestions(num_lists, items_per_list, include_existing_games, include_multiplayer)

    print("simulplay debug - good to here 4")

    return formatted_timeline, story, json.dumps(game_structure_with_media, indent=2), suggestions, selected_list_names #no_media_formatted_timeline, json.dumps(game_structure_without_media, indent=2) #, game_structure_with_media

media_file_types = ["image", "video", "audio"]

def generate_media_file_list(n):
    return [random.choice(media_file_types) for _ in range(n)]


def show_elements(text):
    # Parse the input text
    pattern = r'(\d+): (UI|Story|Media) - (.+)'
    blocks = re.findall(pattern, text)
    
    # Sort blocks by their timestamp
    blocks.sort(key=lambda x: int(x[0]))
    
    outputs = []
    
    for timestamp, block_type, content in blocks:
        if block_type == 'UI':
            # Create HTML for UI elements
            ui_html = f'<div class="ui-element">{content}</div>'
            outputs.append(gr.HTML(ui_html))
        elif block_type == 'Story':
            # Display story elements as Markdown
            outputs.append(gr.Markdown(f"**{content}**"))
        elif block_type == 'Media':
            if content.lower() == 'audio':
                # Placeholder for audio element
                outputs.append(gr.Audio(label=f"Audio at {timestamp} in the order"))
            elif content.lower() == 'video':
                # Placeholder for video element
                outputs.append(gr.Video(label=f"Video at {timestamp} in the order"))
            elif content.lower() == 'image':
                # Placeholder for image element
                outputs.append(gr.Image(label=f"Image at {timestamp} in the order"))
    
    return outputs

def show_elements_json_input(json_input):
    data = json.loads(json_input)
    masterlocation1 = data['masterlocation1']
    
    outputs = []
    
    for location, details in masterlocation1.items():
        if location == 'end':
            continue
        
        with gr.Accordion(f"Location: {location} - Previous description {details['description']}", open=False):
            description = gr.Textbox(label="Description", value=details['description'], interactive=True)
            outputs.append(description)
            
            events = gr.Textbox(label="Events", value=json.dumps(details['events']), interactive=True)
            outputs.append(events)
            
            choices = gr.Textbox(label="Choices", value=json.dumps(details['choices']), interactive=True)
            outputs.append(choices)
            
            transitions = gr.Textbox(label="Transitions", value=json.dumps(details['transitions']), interactive=True)
            outputs.append(transitions)
            
            # New media field
            media = gr.Textbox(label="Media", value=json.dumps(details['media']), interactive=True)
            outputs.append(media)

            # New developernotes field
            developernotes = gr.Textbox(label="developernotes", value=json.dumps(details['developernotes']), interactive=True)
            outputs.append(developernotes)

    #adding/removing a field means incrementing/decreasing the i+n to match the fields
    num_current_unique_fields = 6
    
    def update_json(*current_values):
        updated_data = {"masterlocation1": {}}
        locations = [loc for loc in masterlocation1.keys() if loc != 'end']
        for i, location in enumerate(locations):
            updated_data["masterlocation1"][location] = {
                "description": current_values[i*num_current_unique_fields],
                "events": json.loads(current_values[i*num_current_unique_fields + 1]),
                "choices": json.loads(current_values[i*num_current_unique_fields + 2]),
                "transitions": json.loads(current_values[i*num_current_unique_fields + 3]),
                "media": json.loads(current_values[i*num_current_unique_fields + 4]),  # New media field
                "developernotes": json.loads(current_values[i*num_current_unique_fields + 5])
            }
        updated_data["masterlocation1"]["end"] = masterlocation1["end"]
        return json.dumps(updated_data, indent=2) #json.dumps(updated_data, default=lambda o: o.__dict__, indent=2)
    
    update_button = gr.Button("Update JSON - Still need to copy to correct textbox to load")
    json_output = gr.Textbox(label="Updated JSON - Still need to copy to correct textbox to load", lines=10)
    #json_output = gr.Code(label="Updated JSON", lines=10) #Locks whole UI so use textbox

    update_button.click(update_json, inputs=outputs, outputs=json_output)
    
    return outputs + [update_button, json_output] #, json_output_code]

def show_elements_json_input_play_and_edit_version(json_input):
    data = json.loads(json_input)
    outputs = []

    for location_name, location_data in data.items():
        if location_name == "end":
            continue

        for sub_location, details in location_data.items():
            with gr.Accordion(f"Location: {location_name} - {sub_location}", open=False):
                description = gr.Textbox(label="Description", value=details.get('description', ''), interactive=True)
                outputs.append(description)

                choices = gr.Textbox(label="Choices", value=json.dumps(details.get('choices', [])), interactive=True)
                outputs.append(choices)

                transitions = gr.Textbox(label="Transitions", value=json.dumps(details.get('transitions', {})), interactive=True)
                outputs.append(transitions)

                consequences = gr.Textbox(label="Consequences", value=json.dumps(details.get('consequences', {})), interactive=True)
                outputs.append(consequences)

                media = gr.Textbox(label="Media", value=json.dumps(details.get('media', [])), interactive=True)
                outputs.append(media)

                # Add developernotes field if it exists in the config
                if 'developernotes' in details:
                    developernotes = gr.Textbox(label="Developer Notes", value=details.get('developernotes', ''), interactive=True)
                    outputs.append(developernotes)

    # Determine the number of fields dynamically
    num_current_unique_fields = 5 if 'developernotes' not in next(iter(next(iter(data.values())).values())) else 6

    def update_json(*current_values):
        updated_data = {}
        location_names = list(data.keys())
        location_names.remove("end") if "end" in location_names else None

        value_index = 0
        for location_name in location_names:
            updated_data[location_name] = {}
            sub_locations = list(data[location_name].keys())
            
            for sub_location in sub_locations:
                updated_data[location_name][sub_location] = {
                    "description": current_values[value_index],
                    "choices": json.loads(current_values[value_index + 1]),
                    "transitions": json.loads(current_values[value_index + 2]),
                    "consequences": json.loads(current_values[value_index + 3]),
                    "media": json.loads(current_values[value_index + 4])
                }
                if num_current_unique_fields == 6:
                    updated_data[location_name][sub_location]["developernotes"] = current_values[value_index + 5]
                value_index += num_current_unique_fields

        if "end" in data:
            updated_data["end"] = data["end"]

        return json.dumps(updated_data, indent=2)

    update_button = gr.Button("Update JSON")
    json_output = gr.Textbox(label="Updated JSON", lines=10)

    update_button.click(update_json, inputs=outputs, outputs=json_output)

    return outputs + [update_button, json_output]

def create_media_component(file_path):
    print(file_path)
    _, extension = os.path.splitext(file_path)
    extension = extension.lower()[1:]  # Remove the dot and convert to lowercase

    if extension in ['jpg', 'jpeg', 'png', 'gif', 'webp']:
        return gr.Image(value=file_path, label="Image Input")
    elif extension in ['mp4', 'avi', 'mov']:
        return gr.Video(value=file_path, label="Video Input")
    elif extension in ['mp3', 'wav', 'ogg']:
        return gr.Audio(value=file_path, label="Audio Input")
    else:
        return gr.Textbox(value=file_path, label=f"File: {os.path.basename(file_path)}")

def convert_timeline_to_game_structure(timeline):
    lines = timeline.split('\n')
    game_structure = {}
    current_location = 0
    sub_location = 0

    for i, line in enumerate(lines):
        if line.strip() == "":
            continue
        
        if line[0].isdigit():  # New location starts
            current_location += 1
            sub_location = 0
            location_key = f"location{current_location}"
            game_structure[location_key] = {
                "description": "",
                "events": [],
                "choices": ["continue"],
                "transitions": {},
                "media": [],
                "developernotes": []
            }
        else:  # Continue with sub-locations or media entries
            sub_location += 1
            location_key = f"location{current_location}_{sub_location}"
        
        # Extract the event description
        parts = line.split(': ', 1)
        if len(parts) == 2:
            prefix, rest = parts
            event_parts = rest.split(' - ', 1)
            if len(event_parts) == 2:
                event_type, event_description = event_parts
            else:
                event_type, event_description = "Unknown", rest
        else:
            event_type, event_description = "Unknown", line
        
        description = rest.strip() if event_type in ["Media", "UI"] else f"{event_type}: {event_description}"
        
        if sub_location == 0:
            game_structure[f"location{current_location}"]["description"] = description
        else:
            game_structure[f"location{current_location}"]["events"].append({
                "description": description,
                "type": event_type
            })
        
        # Set the transition to the next location or to the end
        if i < len(lines) - 1:
            next_line = lines[i + 1].strip()
            if next_line and next_line[0].isdigit():  # New location starts
                game_structure[f"location{current_location}"]["transitions"]["continue"] = f"masterlocation1_location{current_location + 1}"
            else:
                #game_structure[f"location{current_location}"]["transitions"]["continue"] = f"location_{current_location}_{sub_location + 1}"
                game_structure[f"location{current_location}"]["transitions"]["continue"] = "end"
        else:
            game_structure[f"location{current_location}"]["transitions"]["continue"] = "end"
    
    # Add an end location
    game_structure["end"] = {
        "description": "The adventure ends here.",
#         "choices": [],
#         "transitions": {}
        "choices": ["restart"],
        "transitions": {"restart": "location1"}  # Assuming location_1 is the start

    }
    
    # Wrap the game structure in master_location1
    wrapped_structure = {"masterlocation1": game_structure}
    
    return wrapped_structure
    
# def generate_game_structures(timeline_with_media): #, timeline_without_media):
    
#     game_structure_with_media = convert_timeline_to_game_structure(timeline_with_media)
#     #game_structure_without_media = convert_timeline_to_game_structure(timeline_without_media)
    
#     return game_structure_with_media #, game_structure_without_media


# def timeline_get_random_suggestions(num_lists, items_per_list):
#     """
#     Generate random suggestions from a specified number of lists.
    
#     :param num_lists: Number of lists to consider
#     :param items_per_list: Number of items to select from each list
#     :return: A list of randomly selected suggestions
#     """
#     selected_lists = random.sample(all_idea_lists, min(num_lists, len(all_idea_lists)))
#     suggestions = []
    
#     for lst in selected_lists:
#         suggestions.extend(random.sample(lst, min(items_per_list, len(lst))))
    
#     return suggestions

def timeline_get_random_suggestions(num_lists, items_per_list, include_existing_games, include_multiplayer):
    """
    Generate random suggestions from a specified number of lists.
    
    :param num_lists: Number of lists to consider
    :param items_per_list: Number of items to select from each list
    :param include_existing_games: Whether to include existing game inspiration lists
    :param include_multiplayer: Whether to include multiplayer features list
    :return: A tuple containing the list of randomly selected suggestions and the names of selected lists
    """
    available_lists = all_idea_lists.copy()
    if not include_existing_games:
        available_lists = [lst for lst in available_lists if lst not in existing_game_inspirations]
    if not include_multiplayer:
        available_lists = [lst for lst in available_lists if lst != multiplayer_features]
    
    selected_lists = random.sample(available_lists, min(num_lists, len(available_lists)))
    suggestions = []
    selected_list_names = []
    
    for lst in selected_lists:
        suggestions.extend(random.sample(lst, min(items_per_list, len(lst))))
        selected_list_names.append(list_names[all_idea_lists.index(lst)])
    
    return suggestions, selected_list_names