Spread the love

I was planning to focus on Game Development for this quarter of the year; but that fell a little flat last week. Between choosing to go sober from the start of this year, and struggling to hold it, I’ve lost a little of the plot for some of my plans. Thankfully, in SA from the previous NaNoWriMo groups, new writing challenges are being created, and likely we will see a few more throughout the year. Today is the start of the:

Words of Winter Write-a-thon

So far, not everyone has updated their word counts for the day, but I can cheat and say I was 3rd for a little bit, at least! As a note, whenever I can find these “distractions,” it helps me when it comes to the sober I’ve been aiming for. I did learn this weekend that I shouldn’t have even 1 to remember a flavour I enjoyed a ton in my past, as it leads to me drinking way more despite not wanting to. I appreciate it was mentioned I should mention it so I can have people understand it’s a bit of a tough choice, especially since it takes me way longer than most other to build any new memory or thought process.

18:16 Graph top scorers today

When I paid attention to the group announcements on WhatsApp, I realised I needed to stop doing Game Dev work for a bit, I’d rather do what I planned for this November Write-a-thon. Move from NaNoE.V2 to a new NaNoE structure.

The structure is rather simple, using the data style from V2 as a point of entry, I ported it over to have a Novel data structure to replace it being an individual file per novel. At first, when porting Accidental Distances to it, so I can also edit that in the new version NaNoE Refresh, I found several flaws. I want to keep historic Deleted novel items (i.e. a paragraph, bookmark, note, or chapter) and manage the order with ease. Importing it to the desktop version worked easily like a charm, the problem came from when I needed to import it on Android.

On Friday, after work, with the Android app giving me issues, still, it clicked. I thought it through a ton and sided towards a unique ID system that has worked wonders. Starting with all models using a standard structure:

namespace NaNoERefresh.Data.Models;

internal class IModel
{
    public DateTime CreatedOn { get; set; } = DateTime.Now;
    public DateTime EditedOn { get; set; } = DateTime.Now;
    public bool Deleted { get; set; } = false;
}

It’s easier to manage the sync, in every table. While the 108,075 words in Accidental Distances takes around 1 minute to sync, the new method of unique ID has been working wonders in testing, and on day 1 of the challenge. I might add on more words to the 1,828 later, but it’s above the minimum required for day 1.

using NaNoERefresh.Data;

namespace NaNoERefresh.Views;

internal static class NewUniqueCode
{
    private static readonly List<char> _characters = new()
    {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
        'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
        'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
        'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
        'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
        'y', 'z', '-', '_', '.', '~', '!', '@', '#', '$',
        '%', '^', '&', '*', '(', ')', '+', '=', '{', '}',
        '[', ']', ':', ';', '"', '\'', '<', '>', ',', '?',
        '/', '\\'
    };

    internal enum TableToBeUniqueIn
    {
        Novel,        // RNovel - NovelCode
        Category,     // WikiCategory - NovelWikiCategory
        Item,         // WikiCategoryItem - NovelWikiCategoryItem
    }

    public static string Generate(TableToBeUniqueIn table)
    {
        var random = new Random();
        var code = new char[16];
        bool continuedForUniqueness = true;
        string answer = "";
        while (continuedForUniqueness)
        {
            for (int i = 0; i < code.Length; i++)
            {
                code[i] = _characters[random.Next(_characters.Count)];
            }
            answer = new string(code);
            switch (table)
            {
                case TableToBeUniqueIn.Novel:
#if ANDROID
                    continuedForUniqueness = MDb.Novels.Any(n => n.NovelCode == answer);
#else
                    continuedForUniqueness = SDb.Novels.Any(n => n.NovelCode == answer);
#endif
                    break;
                case TableToBeUniqueIn.Category:
#if ANDROID
                    continuedForUniqueness = MDb.NovelWikiCategories.Any(c => c.CategoryCode == answer);
#else
                    continuedForUniqueness = SDb.NovelWikiCategories.Any(c => c.CategoryCode == answer);
#endif
                    break;
                case TableToBeUniqueIn.Item:
#if ANDROID
                    continuedForUniqueness = MDb.NovelWikiCategoryItems.Any(i => i.ItemCode == answer);
#else
                    continuedForUniqueness = SDb.NovelWikiCategoryItems.Any(i => i.ItemCode == answer);
#endif
                    break;
            }
        }
        return answer;
    }

    public static string GenerateSuperItemCode()
    {
        var random = new Random();
        var code = new char[16];
        bool continuedForUniqueness = true;
        string answer = "";
        while (continuedForUniqueness)
        {
            for (int i = 0; i < code.Length; i++)
            {
                code[i] = _characters[random.Next(_characters.Count)];
            }
            answer = new string(code);
#if ANDROID
            continuedForUniqueness = MDb.NovelItems.Any(i => i.NovelItemCode == answer) || MDb.NovelWikiCategoryItemNotes.Any(i => i.NovelWikiCategoryItemNoteCode == answer);
#else
            continuedForUniqueness = SDb.NovelItems.Any(i => i.NovelItemCode == answer) || SDb.NovelWikiCategoryItemNotes.Any(i => i.NovelWikiCategoryItemNoteCode == answer);
#endif
        }
        return answer;
    }
}

As programmers can no doubt tell; it’s a rushed implementation. I was going to hit 32 or 64 characters for the code in the second function, but I stopped.

With 92 unique characters for any character in a string; at 16 characters long, is approximately 2.65*(10^30) unique strings possible. Yeah, 10^30 is a Nonillion. I’m sure my math major, programmer, friends will laugh at this at least a little. That’s legit around approximately 1 in a Septillion (10^24) chance of not being unique. So, instead, I manage position as a long value, and update positions whenever a new NovelItem is created. according to its position.

With around 3300 items, as well as around 320 wiki rows, with a unique ID at the start of the day for Accidental Distance (I will publish it when I can, bug me), I’m pretty sure I’m not running out of unique IDs any time soon. A win, of sorts, on its own. If I was in less of a random speed mindset, I would go from 0’s as a string, to the last character, and increment it, but I felt there’s no point spending the extra time after this proved it works on 1 question to Copilot that took 2 seconds to implement.

The main reason for the unique ID happens to be sync between devices. At the moment, I can write on my Android table as well, except it will be the same view as the phone’s version. Version 1, which I’m using, has only simple features:

  • Sync with desktop
  • Create new novel
  • Add any novel item in said novel
  • Tracks word counts and time for sessions
  • Has wiki categories you can set up, add items under, and add notes on each item
  • Either using the Writing page, or the Edit page

Short, sweet, and simple. Having the unique ID was how I managed to have it sync with different individual IDs on other hardware keeping changes linked to the unique IDs. As in, I make a paragraph Novel Item ID “10” on Desktop, and also make a new one on Android that gets the same ID, they both have a unique ID, and the position is used to map where it belongs to put things in the right place.

I do know, I need a method to move Novel Items up and down manually; it could have bugs I haven’t yet encountered. But it’s simple, have a method I can sync between more than one of my devices and can work on all my novels in the same place, sort of. Yeah, I will add in my other novels to progress in them again in the near future, but this time it was make it easy for me to write a new novel from scratch in this style of application.

A sneak peak

The writing section is above, and has an Editor (for multiple lines) to type in. It doesn’t update the word count until you save it as a novel item, but it’s easy enough to use for my writing, now. As such, it looks like so:

The area to write in

Well, there we go; I might release NaNoE Refresh in the future, perhaps, but with this first version, my goal is to write a 50k word novel this month. I chose to randomise the entire idea from a base idea I had. Thanks to Gemma 3 4B Instruct for answering my random sci-fi questions to start this novel. Finally, many thanks to the Jozi & Words of Winter – you’re all awesome and this kind of action will help me stick to my sobriety!