• Willkommen im Forum „Tintenzirkel - das Fantasyautor:innenforum“.
 

Nach dem Nano geht es weiter

Begonnen von Maja, 03. April 2025, 11:56:29

« vorheriges - nächstes »

0 Mitglieder und 1 Gast betrachten dieses Thema.

tarepanDaya

Ich wäre eher für TiZi-NaNo. NaNoWriMo ist belegt, das ist der offizielle NaNo, den es jetzt nicht mehr gibt. Das muss man nicht koopten. Der TiZi-NaNo ist der NaNo hier im Forum. Damit ließe sich einerseits zeigen, dass es unsere eigene Aktion ist, wir aber noch Respekt der ursprünglichen Aktion zollen, ohne die es den NaNo hier im Forum so vermutlich nicht geben würde. Die Abkürzung "NaNo" ginge dann auch nicht verloren und wir müssten nichts krampfhaft umdefinieren.

Just my two cents als Eine, die den NaNo lange vor dem Forum kannte.

Inea

Zitat von: tarepanDaya am 03. September 2025, 12:18:53Ich wäre eher für TiZi-NaNo.

Tintenzirkels natürlich allerwichtigster Monat: November ;)

Shin

NaNo ist das, was wir draus machen.  :flausch:

Ich habe mir trackbear auch mal angeschaut, die Einstellungen für Leaderboards/Gruppen sind zuerst etwas kontraintuitiv, aber sehen mit der API und Statistik echt gut aus.
Ich verstehe aber auch, dass sich so kurzfristig damit auseinander zu setzen anstrengend sein kann und finde Excel auch eine gute Lösung. Ob man Zahlen nun auf einer neuen Seite oder einem Spreadsheet einträgt macht ja nicht wirklich einen Unterschied/mehr Aufwand für den Nutzer.
"The universe works in mysterious ways
But I'm starting to think it ain't working for me."

- AJR
"It's OK, I wouldn't remember me either."        
- Crywank          

Mindi

Zitat von: Rajou am 03. September 2025, 12:07:23Und ich fände es eigentlich cool, wenn wir mal nicht erst 2 Monate vorher anfangen würden, neue Ideen für Statistiktools oder so zu sammeln, sondern mit etwas mehr Vorlauf. Dieses kurzfristige Umhergespringe ist super anstrengend (für mich). Ich würd am liebsten dieses Jahr bei gemeinsamen Excel-Sheets bleiben und dafür dann in Ruhe 12 Monate in das Auslooten eines neuen Tools stecken fürs nächste Jahr.

Aber ... welche 12 Monate? Ich bin lost! Da ist der November, da schreiben wir. Dann ist der Monat mit Weihnachten, dann ist der Monat nach Weihnachten und dann kommt September und Nano steht vor der Tür. Und schwups, schon ist November.  :rofl:

Nein, aber ich sehe das prinzipiell auch so. Und ähm ... Tabelle. Hab ich die nicht letztes Jahr irgendwie mit erstellt oder bei der Vorbereitung geholfen? :rofl:
Wenn wir das wieder so machen, stupst mich bitte nochmal an - ich helfe gern aus.

Generell ist aber zwei Monate vorher immerhin noch mehr Zeit, als 2 Tage vorher. Aber vielleicht können wir auch "im kleinen" in interessierten Battlegruppen das Tool probieren. Ich habe nur keine Ahnung von diesem API-Zeug. :versteck:
"When we are asleep in this world, we are awake in another." - Salvador Dalí

Fianna

Also, wenn andere Leute ihren November ChaNoWriMo nennen, nach ihrer Schreibgruppe, könnten wir doch proud and loud TiNoWriMo nehmen - @Maja wäre das okay für Dich, wenn wir unsere Schreibfortschritte in Social Media so verschlagworten ?

(Ich würde vermutlich #vielschreibmonat dazu nehmen, weil es etabliert ist, und #teamtintenzirkel)

Maja

Der TiNoWriMo ist seit 2006 das gesamte Kampfschreiben im Tintenzirkel, ganzjährig. Ihr dürft das gern als Hashtag bentuzen, aber für mich wird das nie speziell mit dem November verknüpft sein, weswegen ich innerhalb des Forums gern beim bisherigen Namen bleiben möchte.
Niemand hantiert gern ungesichert mit kritischen Massen.
Robert Gernhardt

Maubel

Letztens ist mir über den Scrivener Newsletter folgendes ins Haus geflattert: ProWritingAid hat das Zepter übernommen und richtet den NovelNovember aus, komplett mit Tracker, Badges, Community und Autoren-Motivationsschreiben - und natürlich Partnern (wie jetzt Scrivener). Ich werde mich da jetzt mal anmelden und schauen, aber das wäre vielleicht eine Möglichkeit für alle, die die externe Webseite brauchen oder aber auch für die Statistik.

Fianna

Danke für den Tipp!
Ich habe mich schon registriert: Fiannas Profil bei Novel November

Deven

Hallo liebe Schreiberlinge. Ich habe mir erlaubt einen kleinen in-house Tracker zu basteln. Er funktioniert offline, ist open source, funktioniert wie gewohnt und erlaubt sogar einen eigenen Zeitrahmen mit individuellem Startzeitpunkt zu setzen. Ich hatte noch keine Gelegenheit für einen Langzeittest, falls jemand den Counter testen will, berichtet gerne. Aktuell existiert nur ein direkt ausführbares Programm für Linux, nicht weil die Umsetzung für MacOS und Windows nicht einfach möglich wären, sondern schlicht, weil ich die Plattformen gerade nicht zur Verfügung habe.

Hier ist der Quellcode in Python:

import tkinter as tk
from tkinter import ttk, messagebox
from datetime import datetime, timedelta
import json
import os

SAVE_FILE = "writing_challenge.json"

class WritingChallengeApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Writing Challenge Tracker")

        # State variables
        self.goal_words = tk.IntVar(value=50000)
        self.total_days = tk.IntVar(value=30)
        self.entries = []  # list of {"time": datetime, "words": cumulative_total}
        self.start_date = None
        self.challenge_started = False

        # Load previous save if exists
        self.load_data()

        # UI
        self.setup_ui()
        self.update_stats()
        self.update_status_timer()  # Start the countdown/status updates

    def setup_ui(self):
        # Challenge Settings
        goal_frame = ttk.LabelFrame(self.root, text="Challenge Settings")
        goal_frame.pack(fill="x", padx=10, pady=5)

        ttk.Label(goal_frame, text="Word Goal:").grid(row=0, column=0, sticky="w")
        ttk.Entry(goal_frame, textvariable=self.goal_words).grid(row=0, column=1)

        ttk.Label(goal_frame, text="Total Days:").grid(row=1, column=0, sticky="w")
        ttk.Entry(goal_frame, textvariable=self.total_days).grid(row=1, column=1)

        # Start date/time inputs
        ttk.Label(goal_frame, text="Start Date (YYYY-MM-DD)h:").grid(row=2, column=0, sticky="w")
        self.start_date_entry = ttk.Entry(goal_frame)
        self.start_date_entry.grid(row=2, column=1)
        ttk.Label(goal_frame, text="Start Time in 24 hours (HH:MM:SS):").grid(row=3, column=0, sticky="w")
        self.start_time_entry = ttk.Entry(goal_frame)
        self.start_time_entry.grid(row=3, column=1)

        ttk.Button(goal_frame, text="Start Challenge", command=self.start_challenge).grid(row=4, column=0, pady=5)
        ttk.Button(goal_frame, text="Stop Challenge", command=self.stop_challenge).grid(row=4, column=1, pady=5)

        # Status Label for countdown / started
        self.status_label = ttk.Label(self.root, text="", font=("Arial", 12))
        self.status_label.pack(pady=5)

        # Daily Progress
        entry_frame = ttk.LabelFrame(self.root, text="Daily Progress")
        entry_frame.pack(fill="x", padx=10, pady=5)
        ttk.Button(entry_frame, text="Add Cumulative Word Count", command=self.add_word_count).pack(side="left", padx=5)

        # Stats display
        self.stats_label = ttk.Label(self.root, text="", justify="left", font=("Courier", 11))
        self.stats_label.pack(padx=10, pady=10, fill="x")

    def start_challenge(self):
        if self.start_date is not None:
            messagebox.showinfo("Already Scheduled", f"Challenge already scheduled for {self.start_date.strftime('%Y-%m-%d %H:%M:%S')}")
            return
        try:
            date_str = self.start_date_entry.get()
            time_str = self.start_time_entry.get()
            dt_str = f"{date_str} {time_str}"
            self.start_date = datetime.strptime(dt_str, "%Y-%m-%d %H:%M:%S")
        except Exception:
            messagebox.showerror("Error", "Invalid date or time format. Use YYYY-MM-DD and HH:MM:SS")
            return
        self.entries = []
        self.challenge_started = datetime.now() >= self.start_date
        self.save_data()
        self.update_stats()
        if self.challenge_started:
            messagebox.showinfo("Challenge Started", f"Challenge started at {self.start_date.strftime('%Y-%m-%d %H:%M:%S')}")
        else:
            messagebox.showinfo("Challenge Scheduled", f"Challenge scheduled for {self.start_date.strftime('%Y-%m-%d %H:%M:%S')}")

    def stop_challenge(self):
        confirm = messagebox.askyesno("Stop Challenge", "Are you sure you want to reset the challenge?")
        if confirm:
            self.start_date = None
            self.entries = []
            self.challenge_started = False
            if os.path.exists(SAVE_FILE):
                os.remove(SAVE_FILE)
            self.update_stats()
            self.status_label.config(text="")
            messagebox.showinfo("Challenge Reset", "Challenge has been reset.")

    def add_word_count(self):
        if self.start_date is None:
            messagebox.showerror("Error", "Start the challenge first!")
            return
        if not self.challenge_started:
            messagebox.showerror("Error", "Challenge has not started yet!")
            return

        def save_and_close():
            try:
                cumulative = int(word_entry.get())
                last_total = self.entries[-1]["words"] if self.entries else 0
                if cumulative < last_total:
                    messagebox.showerror("Error", f"Cumulative total cannot be less than last total ({last_total})")
                    return
                self.entries.append({"time": datetime.now(), "words": cumulative})
                self.save_data()
                self.update_stats()
                popup.destroy()
            except ValueError:
                messagebox.showerror("Error", "Please enter a valid number.")

        popup = tk.Toplevel(self.root)
        popup.title("Add Cumulative Word Count")

        ttk.Label(popup, text="Enter current cumulative total:").pack(padx=10, pady=5)
        word_entry = ttk.Entry(popup)
        word_entry.pack(padx=10, pady=5)
        ttk.Button(popup, text="Save", command=save_and_close).pack(pady=5)

    def update_status_timer(self):
        if self.start_date is None:
            self.status_label.config(text="No challenge scheduled.")
        else:
            now = datetime.now()
            if now < self.start_date:
                remaining = self.start_date - now
                days, seconds = remaining.days, remaining.seconds
                hours = seconds // 3600
                minutes = (seconds % 3600) // 60
                seconds = seconds % 60
                self.status_label.config(
                    text=f"Challenge scheduled to start at {self.start_date.strftime('%Y-%m-%d %H:%M:%S')}\n"
                         f"Time until start: {days}d {hours}h {minutes}m {seconds}s"
                )
                self.challenge_started = False
            else:
                if not self.challenge_started:
                    self.challenge_started = True
                    messagebox.showinfo("Challenge Started", "Challenge has now started!")
                self.status_label.config(text="Challenge Started!")
        self.root.after(1000, self.update_status_timer)

    def update_stats(self):
        if self.start_date is None:
            self.stats_label.config(text="No challenge scheduled.")
            return

        total_words = self.entries[-1]["words"] if self.entries else 0

        # Compute per-day totals
        per_day_counts = {}
        for entry in self.entries:
            delta_seconds = (entry["time"] - self.start_date).total_seconds()
            day_index = int(delta_seconds // (24*3600))
            per_day_counts[day_index] = entry["words"]

        # Today's words
        today_index = int((datetime.now() - self.start_date).total_seconds() // (24*3600))
        last_day_total = per_day_counts.get(today_index - 1, 0)
        today_words = per_day_counts.get(today_index, total_words) - last_day_total

        # Average per day
        days_with_words = [per_day_counts[i]-per_day_counts[i-1] if i>0 else per_day_counts[i] for i in sorted(per_day_counts)]
        avg_per_day = sum(days_with_words)/max(len(days_with_words),1) if days_with_words else 0

        # Remaining days
        time_passed = datetime.now() - self.start_date
        days_passed = time_passed.total_seconds() / (24*3600)
        days_left = max(self.total_days.get() - days_passed, 0)

        required_per_day = (self.goal_words.get() - total_words) / days_left if days_left>0 else 0

        # Projected finish
        projected_days = (self.goal_words.get() - total_words)/avg_per_day if avg_per_day>0 else None
        projected_finish = datetime.now() + timedelta(days=projected_days) if projected_days else None

        challenge_end = self.start_date + timedelta(days=self.total_days.get())

        stats = f"Started: {self.start_date.strftime('%Y-%m-%d %H:%M:%S')}\n"
        stats += f"Challenge Ends: {challenge_end.strftime('%Y-%m-%d %H:%M:%S')}\n"
        stats += f"Total Words: {total_words}\n"
        stats += f"Today's Words: {today_words}\n"
        stats += f"Days Passed: {days_passed:.2f}/{self.total_days.get()}\n"
        stats += f"Remaining Days: {days_left:.2f}\n"
        stats += f"Average Per Day: {avg_per_day:.2f}\n"
        stats += f"Required Per Day: {required_per_day:.2f}\n"
        if projected_finish:
            stats += f"Projected Finish (at current rate): {projected_finish.strftime('%Y-%m-%d %H:%M:%S')}\n"
            stats += f"Days Until Finished (at this rate): {projected_days:.2f}\n"
        else:
            stats += f"Projected Finish (at current rate): N/A\n"
            stats += f"Days Until Finished (at this rate): N/A\n"

        self.stats_label.config(text=stats)

    def save_data(self):
        data = {
            "goal_words": self.goal_words.get(),
            "total_days": self.total_days.get(),
            "start_date": self.start_date.isoformat() if self.start_date else None,
            "entries": [{"time": e["time"].isoformat(), "words": e["words"]} for e in self.entries]
        }
        with open(SAVE_FILE, "w") as f:
            json.dump(data, f)

    def load_data(self):
        if os.path.exists(SAVE_FILE):
            with open(SAVE_FILE, "r") as f:
                data = json.load(f)
                self.goal_words.set(data.get("goal_words", 50000))
                self.total_days.set(data.get("total_days", 30))
                if data.get("start_date"):
                    self.start_date = datetime.fromisoformat(data["start_date"])
                    self.challenge_started = datetime.now() >= self.start_date
                self.entries = [{"time": datetime.fromisoformat(e["time"]), "words": e["words"]} for e in data.get("entries", [])]

if __name__ == "__main__":
    root = tk.Tk()
    app = WritingChallengeApp(root)
    root.mainloop()

Falls sich jemand findet, der daraus auf MacOS oder Windows eine ausführbare Datei basteln wollen würde, eine Anleitung kann ich beifügen, ist kein Hexenwerk.  :jau:
Books serve to show a man that those original thoughts of his aren't very new after all.
- Abraham Lincoln