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:

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.

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.

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:

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!