Category: Uncategorized

  • wrist motion timer: app for fitbit versa 2

    the more your wrist moves, the faster the timer will down down. useful for meeting a productivity goal. the numbers do not correspond to time.

    https://mega.nz/file/3d1nzYhJ#qj3GmStohQj7Ka2rAo34Nubjzu5K2ZGw_e0lSmmCHyU

  • calorie timer: app for fitbit versa 2

    the faster you burn calories, the faster the timer will go down. the numbers do not relate to actual time.

    https://mega.nz/file/mc1yXArJ#jKA6PwokYNQ3G_wSrKSfCxXyyEDgg1qdIhx_eExU11U

  • if you are running a launchnodes ethereum validator and are having some difficulty getting it setup (the service-creation-stack is failing to get created), you may want to make sure that you are creating the server in the “eu-west-2” (london) aws region as that seems to be necessary at the time this was posted. if you are reading this way into the future however, things may have changed.

  • Imagine that you were the ceo of Google. Your company was trying to compete in creating a cutting edge technology (in this case it was ai). However you felt like you were falling as a little bit behind the leaders in the field. In this case, it appeared that the reason was that you were a fairly mature company, so you were paying your workers a high salary and the workers had the expectation that their job would be low stress and only 40 hours a week. Meanwhile, the competition was a startup, their workers were making about the same or less, and they were working 60+ hours a week. If you were the ceo of Google, would it be possible to lower the base pay of your employees and then offer significant bonuses to those people who were willing to really dedicate themselves to the job and work 60+ hours per week? It seems like the only alternatives, and they don’t seem very good, are too either try to force the employees to work more hours which is likely to be very bad for employee morale or to just accept that you are going to lose to the competition.

    If I were the CEO of Google in this scenario, I’d recognize that I’m facing a classic trade-off between worker incentives, company culture, and competitive pressure. Here’s how I’d think about it:

    Would It Be Possible to Lower Base Pay and Introduce Performance-Based Bonuses?

    Technically, yes—but it would be extremely difficult in practice. Google’s workforce is made up of highly skilled professionals who have choices. Cutting base salaries would likely result in a talent drain, with top employees leaving for competitors (including the startup we’re competing against).

    Instead of reducing base salaries, a better approach would be to increase the upside potential for those who go above and beyond. This could be done through:

    Stock Grants & Options: Giving employees the potential for a big payoff if they work harder and drive AI breakthroughs.

    Tiered Bonus Structures: Offering significant bonuses for those who contribute to mission-critical projects and work extended hours.

    Internal AI Skunkworks Teams: Creating a startup-like environment within Google, where employees voluntarily sign up for an intense, high-reward, high-pressure AI research track.

    Alternative Solutions

    If forcing longer hours or cutting pay isn’t ideal, I’d consider other ways to increase Google’s competitive edge:

    1. Improve AI Research Efficiency – Instead of brute-forcing with more work hours, I’d invest in better tools, infrastructure, and automation to accelerate research without burning out employees.
    2. Selective Hiring for the Most Intense Projects – Google could bring in a subset of highly motivated, startup-style researchers who are willing to work long hours in exchange for outsized rewards.
    3. Acquisitions & Partnerships – If the startup is ahead, buying them or partnering with them could be more effective than trying to outwork them with existing employees.
    4. Strategic Project Selection – Instead of competing on raw effort, focus on AI projects where Google’s resources and data advantage give it an edge, even if the competition is working longer hours.

    Conclusion

    Trying to cut pay while asking for more hours would likely backfire. Instead, I’d focus on creating an environment where the most ambitious employees can thrive—without alienating those who prefer work-life balance. Balancing incentives, efficiency, and strategic focus would be the best way to stay competitive.

  • to get ubuntu 24.04 to stop showing update notifications

    note that i just tried this and am not sure if it actually works:
    - sudo nano /etc/xdg/autostart/update-notifier.desktop
    	- change "NoDisplay=true" to "NoDisplay=false"
    - open "startup applications"
    	+ uncheck 'update notifier'
    - open dconf
    	+ go to com > ubuntu > update-notifier
    		* change regular-auto-launch-interval to a really high number
  • python script to help sort directories containing one text file each

    add this script to “actions for nautilus”

    import os
    import shutil
    import tkinter as tk
    from tkinter import scrolledtext, messagebox, filedialog
    from tkinter import font as tkfont
    from tkinter import ttk
    
    class DirectoryMoverApp(tk.Tk):
        def __init__(self, main_dir):
            super().__init__()
    
            self.main_dir = main_dir
            self.dir_list = sorted(list_subdirectories(main_dir), key=lambda x: x.lower())  # Sort directories alphabetically
            self.destination_dirs = []
            self.moved_dirs = []
            self.last_moved_dir = None
            self.current_index = 0  # Track which subdirectory we're on
            self.moved_counter = 0  # Counter for moved directories
    
            self.load_destinations()
            self.create_widgets()
            self.display_subdirectories()
    
        def load_destinations(self):
            script_dir = os.path.dirname(os.path.realpath(__file__))
            dest_file = os.path.join(script_dir, 'destination_dirs.txt')
    
            try:
                with open(dest_file, 'r') as file:
                    self.destination_dirs = sorted(
                        [line.strip() for line in file.readlines()],
                        key=lambda x: os.path.basename(x).lower()
                    )
            except FileNotFoundError:
                messagebox.showerror("Error", "Destination directories file not found!")
                self.destination_dirs = []
    
        def create_widgets(self):
            self.title("Directory Mover")
            self.geometry(f"{int(self.winfo_screenwidth()*1/2)}x{int(self.winfo_screenheight()*2/3)}")
            self.center_window()
    
            self.subdir_label = tk.Label(self, text="Current Directory: ", font=("Arial", 14))
            self.subdir_label.grid(row=0, column=0, padx=10, pady=5, sticky="w")
    
            self.text_file_counter_label = tk.Label(self, text="Text File Count: ", font=("Arial", 12))
            self.text_file_counter_label.grid(row=1, column=0, padx=10, pady=5, sticky="w")
    
            self.file_contents_field = scrolledtext.ScrolledText(self, wrap=tk.WORD, width=80, height=35)
            self.grid_columnconfigure(0, weight=1, uniform="file_contents")
            self.file_contents_field.grid_propagate(False)
            self.file_contents_field.grid(row=2, column=0, rowspan=4, padx=10, pady=10, sticky="nsew")
    
            self.right_frame = tk.Frame(self)
            self.right_frame.grid(row=2, column=1, padx=10, pady=10, sticky="nsew")
    
            self.counter_label = tk.Label(self.right_frame, text=f"Moved directories: {self.moved_counter}", font=("Arial", 12))
            self.counter_label.pack(pady=10)
    
            self.edit_button = tk.Button(self.right_frame, text="Edit Destinations", command=self.edit_destinations, fg="blue")
            self.edit_button.pack(pady=10)
    
            self.reload_button = tk.Button(self.right_frame, text="Reload Destinations", command=self.reload_destinations, fg="blue")
            self.reload_button.pack(pady=10)
    
            self.undo_button = tk.Button(self.right_frame, text="Undo last move", command=self.undo_last_move, state=tk.DISABLED, fg="red")
            self.undo_button.pack(pady=10)
    
            self.separator_label = tk.Label(self.right_frame, text="-------------------------------------", font=("Arial", 12))
            self.separator_label.pack(pady=10)
    
            self.move_label = tk.Label(self.right_frame, text="Move to:", font=("Arial", 12))
            self.move_label.pack(pady=10)
    
            self.select_directory_button = tk.Button(
                self.right_frame,
                text="Select Directory",
                fg="green",
                command=self.select_directory_action
            )
            self.select_directory_button.pack(pady=10)
    
            self.move_frame = tk.Frame(self)
            self.move_frame.grid(row=3, column=1, padx=10, pady=10, sticky="nsew")
    
            self.move_buttons = []
            self.create_move_buttons()
    
        def create_move_buttons(self, max_buttons_per_column=9):
            row = 0
            col = 0
    
            for i, dir_name in enumerate(self.destination_dirs):
                btn = tk.Button(
                    self.move_frame,
                    text=f"{os.path.basename(dir_name)}",
                    fg="green",
                    command=lambda d=dir_name: self.move_to_directory(d)
                )
                btn.grid(row=row, column=col, padx=5, pady=5)
    
                self.move_buttons.append(btn)
                row += 1
                if row >= max_buttons_per_column:
                    row = 0
                    col += 1
    
        def select_directory_action(self):
            directory = filedialog.askdirectory(initialdir=self.main_dir, title="Select a Directory")
            if directory and os.path.isdir(directory):
                self.move_to_directory(directory)
    
        def display_subdirectories(self):
            if self.current_index < len(self.dir_list):
                subdir = self.dir_list[self.current_index]
                self.subdir_label.config(text=f"Current Directory: {subdir}")
    
                full_path = os.path.join(self.main_dir, subdir)
                content = get_first_txt_md_content(full_path)
    
                self.file_contents_field.delete(1.0, tk.END)
                self.file_contents_field.insert(tk.END, content)
    
                check_text_md_files(full_path, self.text_file_counter_label)
            else:
                self.subdir_label.config(text="Current Directory: None")
                self.file_contents_field.delete(1.0, tk.END)
                self.file_contents_field.insert(tk.END, "Sorting Completed!")
    
        def move_to_directory(self, destination):
            if self.current_index < len(self.dir_list):
                selected_dir_name = self.dir_list[self.current_index]
                selected_dir_path = os.path.join(self.main_dir, selected_dir_name)
                dest_dir_path = os.path.join(destination, selected_dir_name)
    
                os.makedirs(dest_dir_path, exist_ok=True)
                for root, dirs, files in os.walk(selected_dir_path):
                    relative_path = os.path.relpath(root, selected_dir_path)
                    target_root = os.path.join(dest_dir_path, relative_path)
    
                    os.makedirs(target_root, exist_ok=True)
                    for file in files:
                        src_file = os.path.join(root, file)
                        dest_file = os.path.join(target_root, file)
                        if os.path.exists(dest_file):
                            base, ext = os.path.splitext(file)
                            counter = 1
                            new_dest_file = f"{os.path.join(target_root, base)}_{counter}{ext}"
                            while os.path.exists(new_dest_file):
                                counter += 1
                                new_dest_file = f"{os.path.join(target_root, base)}_{counter}{ext}"
                            dest_file = new_dest_file
    
                        shutil.move(src_file, dest_file)
    
                if selected_dir_path != dest_dir_path:
                    shutil.rmtree(selected_dir_path)
                self.moved_dirs.append(selected_dir_path)
                self.last_moved_dir = selected_dir_path
                self.moved_counter += 1
                self.counter_label.config(text=f"Moved directories: {self.moved_counter}")
                self.undo_button.config(state=tk.NORMAL)
    
                self.current_index += 1
                self.display_subdirectories()
    
        def undo_last_move(self):
            if self.last_moved_dir:
                original_path = os.path.join(self.main_dir, self.last_moved_dir)
                shutil.move(self.last_moved_dir, original_path)
                self.moved_counter -= 1
                self.counter_label.config(text=f"Moved directories: {self.moved_counter}")
                self.undo_button.config(state=tk.DISABLED)
    
        def edit_destinations(self):
            script_dir = os.path.dirname(os.path.realpath(__file__))
            dest_file = os.path.join(script_dir, 'destination_dirs.txt')
            os.system(f"xdg-open {dest_file}")
    
        def reload_destinations(self):
            self.load_destinations()
            for btn in self.move_buttons:
                btn.destroy()
            self.move_buttons.clear()
            self.create_move_buttons()
    
        def center_window(self):
            self.update_idletasks()
            width = self.winfo_width()
            height = self.winfo_height()
            x = (self.winfo_screenwidth() // 2) - (width // 2)
            y = (self.winfo_screenheight() // 2) - (height // 2)
            self.geometry(f'{width}x{height}+{x}+{y}')
    
    def list_subdirectories(main_dir):
        return [d for d in os.listdir(main_dir) if os.path.isdir(os.path.join(main_dir, d))]
    
    def check_text_md_files(directory, text_file_counter_label):
        file_extensions = ('.txt', '.md')
        total_files = sum(1 for file in os.listdir(directory) if file.endswith(file_extensions))
        if total_files > 1:
            text_file_counter_label.config(fg="red")
        else:
            text_file_counter_label.config(fg="black")
        text_file_counter_label.config(text=f"Total .txt/.md files: {total_files}")
    
    def get_first_txt_md_content(subdir):
        for file in os.listdir(subdir):
            if file.endswith('.txt') or file.endswith('.md'):
                with open(os.path.join(subdir, file), 'r') as f:
                    return f.read()
        return "No .txt or .md file found."
    
    if __name__ == "__main__":
        import sys
        if len(sys.argv) != 2:
            print("Usage: python3 app.py <directory_path>")
            sys.exit(1)
    
        main_directory = sys.argv[1]
        if not os.path.isdir(main_directory):
            print(f"Error: {main_directory} is not a valid directory.")
            sys.exit(1)
    
        app = DirectoryMoverApp(main_directory)
        app.mainloop()
    
  • python script to convert text to audiobook

    '''
    prerequisites:
      on ubuntu 22.04 or older:
          pip3 install pydub
          pip3 install coqui-tts
      on newer operating systems run the commands in a virtual python environment
          and use 'pip' instead of 'pip3'
    '''
    
    import sys
    import os
    import psutil
    import chardet  # You may need to install this library: pip install chardet
    import tempfile
    import shutil
    from pydub import AudioSegment
    import subprocess
    
    # Conditional import of TTS
    #TTS = None
    
    def is_script_already_running(script_name):
        """Check if another instance of the script is running."""
        current_pid = os.getpid()
        for proc in psutil.process_iter(attrs=['pid', 'name', 'cmdline']):
            try:
                if proc.info['pid'] != current_pid and script_name in proc.info['cmdline']:
                    return True
            except (psutil.NoSuchProcess, psutil.AccessDenied):
                continue
        return False
    
    def detect_encoding(file_path):
        """Detect the encoding of a text file."""
        with open(file_path, 'rb') as f:
            result = chardet.detect(f.read(100000))  # Analyze a portion of the file
        return result['encoding']
    
    def split_text_into_chunks(text, max_words=50):
        """Split text into chunks of approximately max_words, avoiding sentence splits."""
        words = text.split()
        chunks = []
        chunk = []
        word_count = 0
    
        for word in words:
            chunk.append(word)
            word_count += 1
            if word_count >= max_words and (word.endswith('.') or len(word) > max_words + 25):
                chunks.append(' '.join(chunk))
                chunk = []
                word_count = 0
    
        if chunk:
            chunks.append(' '.join(chunk))
    
        return chunks
    
    def create_audio_chunk(chunk_text, chunk_path, model, speaker):
        """Generate TTS audio for a single chunk."""
        # global TTS
        # if TTS is None:
        #     from TTS.api import TTS  # Import only if needed
        
        # tts = TTS(model_name=model)
        # tts.tts_to_file(text=chunk_text, file_path=chunk_path)
        
        '''
        note that if you are using a single speaker model, remove the parameter "--speaker_idx"
    
        if you are using '--speaker_idx "ED"', and you get an error then you may need to correct a bug:
            open file: nano /root/.local/share/tts/tts_models--en--vctk--vits/speaker_ids.json
            change '"ED\n": 0,' to '"ED": 0,'
            save and exit
        '''
        command = [
            'tts',
            '--text', chunk_text,
            '--model_name', model,
            '--speaker_idx', speaker,
            '--out_path', chunk_path
        ]
    
        result = subprocess.run(command, capture_output=True, text=True)
        output = result.stdout + result.stderr  # Capture both stdout and stderr
        print(output)
    
    def join_audio_files(audio_files, output_file):
        """Join multiple audio files into one final output file. Returns True when finished."""
        combined = AudioSegment.empty()
        for file in audio_files:
            combined += AudioSegment.from_file(file)
        combined.export(output_file, format="ogg")
        return True
    
    def convert_text_to_audio(input_file, output_file, model, speaker):
        """Convert text to audio and save as a file. Returns True if it thinks that it has succeeded, otherwise False."""
        temp_dir = None
        final_audio_created = False
        try:
            # Detect file encoding
            encoding = detect_encoding(input_file)
            if not encoding:
                raise ValueError("Could not detect file encoding")
    
            # Read the input text
            with open(input_file, 'r', encoding=encoding, errors='replace') as file:
                text = file.read()
    
            # Split text into chunks if necessary
            chunks = split_text_into_chunks(text)
    
            if not chunks:
                print("No text to convert.")
                return
    
            # Temporary directory for storing audio chunks
            temp_dir = tempfile.mkdtemp()
            temp_audio_files = []
    
            for i, chunk in enumerate(chunks):
                temp_audio_path = os.path.join(temp_dir, f"chunk_{i}.ogg")
                create_audio_chunk(chunk, temp_audio_path, model, speaker)
                temp_audio_files.append(temp_audio_path)
    
            # Join all temporary audio files into the final output file
            final_audio_created = join_audio_files(temp_audio_files, output_file)
    
            print(f"Audio file successfully saved to {output_file}")
        except Exception as e:
            print(f"Error: {e}")
            if temp_dir:
                print(f"Temporary files are saved in {temp_dir} for debugging.")
        finally:
            # Clean up temporary audio files only if the final audio file was created
            if temp_dir and final_audio_created:
                shutil.rmtree(temp_dir)
                return True
            else:
                return False
    
    def process_files(input_dir, output_dir, model="tts_models/en/vctk/vits", speaker="ED"):
        """Process all text and markdown files in the input directory."""
        '''
        model "tts_models/en/jenny/jenny" (irish accent) is good, but is quite slow to process. note that this is a single speaker model and requires a slightly different command.
        model="tts_models/en/vctk/vits", speaker="ED" is quick to process. voice quality is fairly good, but the speaker speaks sort of fast which makes it harder to understand and it is a british accent
        you may want to go through the voice models and see which one works best
        '''
        files_to_process = []
    
        for root, _, files in os.walk(input_dir):
            for file in files:
                if file.endswith(('.txt', '.md')):
                    files_to_process.append(os.path.join(root, file))
    
        if not files_to_process:
            print("No files to process.")
            return
    
        for input_file in files_to_process:
            relative_path = os.path.relpath(os.path.dirname(input_file), input_dir)
            output_subdir = os.path.join(output_dir, relative_path)
    
            # Ensure the output subdirectory exists
            os.makedirs(output_subdir, exist_ok=True)
    
            # Ensure unique output file names
            base_name = os.path.splitext(os.path.basename(input_file))[0]
            output_file = os.path.join(output_subdir, f"{base_name}.ogg")
            counter = 1
            while os.path.exists(output_file):
                output_file = os.path.join(output_subdir, f"{base_name}_{counter}.ogg")
                counter += 1
    
            # Convert text to audio
            success = convert_text_to_audio(input_file, output_file, model, speaker)
    
            # Move the original text file to the output directory
            if success:
                os.rename(input_file, os.path.join(output_subdir, os.path.basename(input_file)))
    
    if __name__ == "__main__":
        if is_script_already_running(sys.argv[0]):
            print("Error: Another instance of the script is already running.")
            sys.exit(1)
    
        if len(sys.argv) != 3:
            print("Usage: python script.py <input_directory> <output_directory>")
            sys.exit(1)
    
        input_dir = sys.argv[1]
        output_dir = sys.argv[2]
    
        # Ensure the input directory exists
        if not os.path.exists(input_dir):
            print(f"Error: The directory {input_dir} does not exist.")
            sys.exit(1)
    
        # Ensure the output directory exists
        os.makedirs(output_dir, exist_ok=True)
    
        # Process the files
        process_files(input_dir, output_dir)