diff --git a/seeker/report.txt b/seeker/report.txt index bb171027..685276c3 100644 --- a/seeker/report.txt +++ b/seeker/report.txt @@ -1,3 +1,38 @@ +-------------------------------------------------------------------------------- + 2024-12-05 17:13:54.476866 +-------------------------------------------------------------------------------- + On branch main +Your branch is up to date with 'origin/main'. + +Changes not staged for commit: + (use "git add/rm ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + deleted: snippet/DS_CodingChallengeSolution_VaibhavSharma + deleted: snippet/UDPClient.java + deleted: snippet/UDPServer.java + deleted: snippet/get_list_of_suites_with_tag.py + modified: snippet/headline.zsh + deleted: snippet/lol_worlds_simulator.py + deleted: snippet/ola.py + deleted: snippet/read_csv_with_pandas.py + deleted: snippet/reset-foundry-version-to-monorepo.sh + deleted: snippet/ssh_hole.sh + +Untracked files: + (use "git add ..." to include in what will be committed) + snippet/.bashrc + snippet/IRCClient.java + snippet/IRCServer.java + snippet/RandomizePlaylist.sh + snippet/fix_labs.py + snippet/go-install.sh + snippet/modbusserver.py + snippet/mount_vbox_shared_folder.sh + snippet/run1 + snippet/yaml_merger.py + +no changes added to commit (use "git add" and/or "git commit -a") + -------------------------------------------------------------------------------- 2024-12-04 17:13:54.644919 -------------------------------------------------------------------------------- diff --git a/seeker/snippet/.bashrc b/seeker/snippet/.bashrc new file mode 100644 index 00000000..7836c838 --- /dev/null +++ b/seeker/snippet/.bashrc @@ -0,0 +1,8 @@ +#date: 2024-12-05T17:12:02Z +#url: https://api.github.com/gists/5cc903d166dcdc0cc7c545608454ec28 +#owner: https://api.github.com/users/jcrtexidor + +# ~/.bashrc + +... +source ~/.cmd/mount_vbox_shared_folder.sh \ No newline at end of file diff --git a/seeker/snippet/DS_CodingChallengeSolution_VaibhavSharma b/seeker/snippet/DS_CodingChallengeSolution_VaibhavSharma deleted file mode 100644 index 9e50b61a..00000000 --- a/seeker/snippet/DS_CodingChallengeSolution_VaibhavSharma +++ /dev/null @@ -1,79 +0,0 @@ -#date: 2024-12-03T16:58:55Z -#url: https://api.github.com/gists/96ceaaa003ee2fc172c36da6239f5176 -#owner: https://api.github.com/users/vash02 - -#!/usr/bin/env python -# coding: utf-8 - -# ## Problem 1 - -# In[22]: - - -#Find pair with sum 2020 and return the product - -def find_2020_pair(filename, target_sum = 2020): - with open(filename, "r") as file: - numbers = [int(line.strip()) for line in file] - - #Set to store the number already visited while iterating and ensuring O(1) retrieval - visited = set() - for num1 in numbers: - num2 = target_sum - num1 - # If num2 is in visited, we find our pair - if num2 in visited: - print(f"num1={num1} and num2={num2}") - return num1 * num2 - # add num1 to visited set on each iteration - visited.add(num1) - - return 0 - - -# In[23]: - - -#I saved the file from github as ds_coding_challenge_dataset.txt, th file is uploaded to github repository too - -#Finding pair summing to 2020 and return the product of the pair -find_2020_pair('dataset') #Name of the dataset file - - -# ## Problem 2 - -# In[24]: - - -#finding group of 3 integers summing up to 2020 - -def sum_2020_triplet(filename, target_sum = 2020): - with open(filename, "r") as file: - numbers = [int(line.strip()) for line in file] - - #Again we use set to ensure search operation is O(1) - for i in range(len(numbers)): - # we initialise visited set here to ensure - visited = set() - curr_sum = target_sum - numbers[i] - for j in range(i+1, len(numbers)): - num3 = curr_sum - numbers[j] - if num3 in visited: - print(f"num1={numbers[i]}, num2={numbers[j]} and num3={num3}") - return numbers[i] * numbers[j] * num3 - visited.add(numbers[j]) - - return 0 - - -# In[26]: - - -#Same file for getting triplets summing to 2020 -sum_2020_triplet('dataset') #Name of the dataset file - - -# In[ ]: - - - - diff --git a/seeker/snippet/IRCClient.java b/seeker/snippet/IRCClient.java new file mode 100644 index 00000000..7e0cb28e --- /dev/null +++ b/seeker/snippet/IRCClient.java @@ -0,0 +1,47 @@ +//date: 2024-12-05T17:02:42Z +//url: https://api.github.com/gists/0cd5acc824db730c068a18840d18d8ba +//owner: https://api.github.com/users/acostaRossi + +import java.io.*; +import java.net.*; + +public class IRCClient { + private static final String SERVER_ADDRESS = "localhost"; + private static final int SERVER_PORT = 6667; + + public static void main(String[] args) { + try { + Socket socket = new Socket(SERVER_ADDRESS, SERVER_PORT); + BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + PrintWriter out = new PrintWriter(socket.getOutputStream(), true); + BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); + + System.out.println("Connesso al server IRC!"); + System.out.println("Per uscire digita '/quit'"); + + // Thread per leggere i messaggi dal server + Thread serverListener = new Thread(() -> { + try { + String message; + while ((message = in.readLine()) != null) { + System.out.println(message); + } + } catch (IOException e) { + System.err.println("Connessione persa con il server."); + } + }); + serverListener.start(); + + // Legge i messaggi dalla console e li invia al server + String userInput; + while ((userInput = console.readLine()) != null) { + out.println(userInput); + if (userInput.equalsIgnoreCase("/quit")) { + break; + } + } + } catch (IOException e) { + System.err.println("Errore nella connessione al server: " + e.getMessage()); + } + } +} diff --git a/seeker/snippet/IRCServer.java b/seeker/snippet/IRCServer.java new file mode 100644 index 00000000..38b288cb --- /dev/null +++ b/seeker/snippet/IRCServer.java @@ -0,0 +1,93 @@ +//date: 2024-12-05T17:02:42Z +//url: https://api.github.com/gists/0cd5acc824db730c068a18840d18d8ba +//owner: https://api.github.com/users/acostaRossi + +import java.io.*; +import java.net.*; +import java.util.*; + +public class IRCServer { + private static final int PORT = 6667; // Porta standard IRC + private static Set clients = new HashSet<>(); + + public static void main(String[] args) { + System.out.println("IRC Server avviato sulla porta " + PORT); + + try (ServerSocket serverSocket = new ServerSocket(PORT)) { + while (true) { + Socket clientSocket = serverSocket.accept(); + System.out.println("Nuovo client connesso: " + clientSocket.getInetAddress()); + ClientHandler clientHandler = new ClientHandler(clientSocket); + clients.add(clientHandler); + new Thread(clientHandler).start(); + } + } catch (IOException e) { + System.err.println("Errore nel server: " + e.getMessage()); + } + } + + // Invia un messaggio a tutti i client connessi + public static void broadcast(String message, ClientHandler sender) { + for (ClientHandler client : clients) { + if (client != sender) { + client.sendMessage(message); + } + } + } + + // Rimuove un client dalla lista quando si disconnette + public static void removeClient(ClientHandler clientHandler) { + clients.remove(clientHandler); + System.out.println("Client disconnesso."); + } + + // Classe per gestire un singolo client + private static class ClientHandler implements Runnable { + private Socket socket; + private PrintWriter out; + private String nickname; + + public ClientHandler(Socket socket) { + this.socket = socket; + } + + @Override + public void run() { + try { + BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + out = new PrintWriter(socket.getOutputStream(), true); + + // Richiede il nickname + out.println("Benvenuto nel server IRC! Inserisci il tuo nickname:"); + nickname = in.readLine(); + System.out.println(nickname + " si è unito alla chat."); + broadcast(nickname + " è entrato nella chat!", this); + + // Legge i messaggi dal client + String message; + while ((message = in.readLine()) != null) { + if (message.equalsIgnoreCase("/quit")) { + break; + } + System.out.println(nickname + ": " + message); + broadcast(nickname + ": " + message, this); + } + } catch (IOException e) { + System.err.println("Errore con il client: " + e.getMessage()); + } finally { + try { + socket.close(); + } catch (IOException e) { + System.err.println("Errore durante la chiusura della connessione: " + e.getMessage()); + } + removeClient(this); + broadcast(nickname + " ha lasciato la chat.", this); + } + } + + // Invia un messaggio a questo client + public void sendMessage(String message) { + out.println(message); + } + } +} diff --git a/seeker/snippet/RandomizePlaylist.sh b/seeker/snippet/RandomizePlaylist.sh new file mode 100644 index 00000000..9e8f13cf --- /dev/null +++ b/seeker/snippet/RandomizePlaylist.sh @@ -0,0 +1,44 @@ +#date: 2024-12-05T17:06:03Z +#url: https://api.github.com/gists/181756472003152136f7bc0284a0dec1 +#owner: https://api.github.com/users/Ne0n09 + +#!/bin/bash + +# Run script with playlist name in the format of 'your playlist' +# If the playlist has spaces in the name put quotes around it + +# Define the base directory +BASE_DIR="/home/fpp/media/playlists" + +# Check if argument is provided +if [ -z "$1" ]; then + echo "Error: No playlist name provided. Please provide a playlist name." + exit 1 +fi + +# Set the PLAYLIST variable from the $1 argument +PLAYLIST="$1" + +# Remove any surrounding spaces +PLAYLIST=$(echo "$PLAYLIST" | xargs) + +# Construct the full file path +INPUT_FILE="$BASE_DIR/$PLAYLIST.json" + +# Check if the playlist file exists +if [ ! -f "$INPUT_FILE" ]; then + echo "Error: File '$INPUT_FILE' not found in directory '$BASE_DIR'." + exit 1 +fi + +# Shuffle the JSON array using Python +python3 -c " +import json, random +with open('$INPUT_FILE', 'r') as f: + data = json.load(f) +data['mainPlaylist'] = random.sample(data['mainPlaylist'], len(data['mainPlaylist'])) +with open('$INPUT_FILE', 'w') as f: + json.dump(data, f, indent=4) +" + +echo "Randomized sequences written back to $INPUT_FILE" \ No newline at end of file diff --git a/seeker/snippet/UDPClient.java b/seeker/snippet/UDPClient.java deleted file mode 100644 index d84d0a6f..00000000 --- a/seeker/snippet/UDPClient.java +++ /dev/null @@ -1,44 +0,0 @@ -//date: 2024-12-03T16:52:53Z -//url: https://api.github.com/gists/79eef5d8f305bef479edef1ccd09659b -//owner: https://api.github.com/users/acostaRossi - -import java.net.*; -import java.util.Scanner; - -public class UDPClient { - public static void main(String[] args) { - String serverHost = "localhost"; - int serverPort = 9876; - - try (DatagramSocket clientSocket = new DatagramSocket()) { - InetAddress serverAddress = InetAddress.getByName(serverHost); - Scanner scanner = new Scanner(System.in); - - while (true) { - System.out.print("Indovina un numero (1-100): "); - String guess = scanner.nextLine(); - - // Invia il messaggio al server - byte[] sendBuffer = guess.getBytes(); - DatagramPacket sendPacket = new DatagramPacket(sendBuffer, sendBuffer.length, serverAddress, serverPort); - clientSocket.send(sendPacket); - - // Riceve la risposta dal server - byte[] receiveBuffer = new byte[1024]; - DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length); - clientSocket.receive(receivePacket); - - String serverResponse = new String(receivePacket.getData(), 0, receivePacket.getLength()); - System.out.println("Risposta del server: " + serverResponse); - - // Se il numero è corretto, termina il gioco - if (serverResponse.contains("Corretto")) { - System.out.println("Hai vinto!"); - break; - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/seeker/snippet/UDPServer.java b/seeker/snippet/UDPServer.java deleted file mode 100644 index 864c6b9b..00000000 --- a/seeker/snippet/UDPServer.java +++ /dev/null @@ -1,60 +0,0 @@ -//date: 2024-12-03T16:52:53Z -//url: https://api.github.com/gists/79eef5d8f305bef479edef1ccd09659b -//owner: https://api.github.com/users/acostaRossi - -import java.net.*; -import java.util.Random; - -public class UDPServer { - public static void main(String[] args) { - int port = 9876; - Random random = new Random(); - int targetNumber = random.nextInt(100) + 1; // Numero casuale tra 1 e 100 - - System.out.println("Server avviato. Numero da indovinare: " + targetNumber); - - try (DatagramSocket serverSocket = new DatagramSocket(port)) { - byte[] receiveBuffer = new byte[1024]; - byte[] sendBuffer; - - while (true) { - // Ricezione dei dati dal client - DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length); - serverSocket.receive(receivePacket); - - String clientMessage = new String(receivePacket.getData(), 0, receivePacket.getLength()); - System.out.println("Ricevuto dal client: " + clientMessage); - - // Analisi del messaggio del client - int guessedNumber; - try { - guessedNumber = Integer.parseInt(clientMessage.trim()); - } catch (NumberFormatException e) { - guessedNumber = -1; // Valore non valido - } - - String response; - if (guessedNumber == targetNumber) { - response = "Corretto! Hai indovinato!"; - System.out.println("Numero indovinato dal client!"); - targetNumber = random.nextInt(100) + 1; // Nuovo numero da indovinare - System.out.println("Nuovo numero da indovinare: " + targetNumber); - } else if (guessedNumber < targetNumber) { - response = "Troppo basso!"; - } else { - response = "Troppo alto!"; - } - - // Invio della risposta al client - InetAddress clientAddress = receivePacket.getAddress(); - int clientPort = receivePacket.getPort(); - sendBuffer = response.getBytes(); - - DatagramPacket sendPacket = new DatagramPacket(sendBuffer, sendBuffer.length, clientAddress, clientPort); - serverSocket.send(sendPacket); - } - } catch (Exception e) { - e.printStackTrace(); - } - } -} diff --git a/seeker/snippet/fix_labs.py b/seeker/snippet/fix_labs.py new file mode 100644 index 00000000..e4b5bd1f --- /dev/null +++ b/seeker/snippet/fix_labs.py @@ -0,0 +1,38 @@ +#date: 2024-12-05T17:01:10Z +#url: https://api.github.com/gists/b1f21a303bfc5bdaec8f869388a9fda3 +#owner: https://api.github.com/users/Nikh1l + +import os +import shutil + +root_dir = "D:\Productive\Plugins\SplitFire\Spitfire Audio - LABS" +source_folders = ["Patches", "Presets", "Samples"] + +def reorganise_labs_folder(): + matching_folders = set() + + for folder in source_folders: + folder_path = os.path.join(root_dir, folder) + + if os.path.exists(folder_path): + sub_folders = [name for name in os.listdir(folder_path) if os.path.isdir(os.path.join(folder_path, name))] + if not matching_folders: + matching_folders.update(sub_folders) + else: + matching_folders.intersection_update(sub_folders) + + for match in matching_folders: + destination = os.path.join(root_dir, match) + os.makedirs(destination, exist_ok=True) + + for folder in source_folders: + source_path = os.path.join(root_dir, folder, match) + dest_path = os.path.join(destination, folder) + + if os.path.exists(source_path): + shutil.copytree(source_path, dest_path, dirs_exist_ok=True) + print(f"Copied from {source_path} to {dest_path}") + + +if __name__ == "__main__": + reorganise_labs_folder() \ No newline at end of file diff --git a/seeker/snippet/get_list_of_suites_with_tag.py b/seeker/snippet/get_list_of_suites_with_tag.py deleted file mode 100644 index 3bef2c46..00000000 --- a/seeker/snippet/get_list_of_suites_with_tag.py +++ /dev/null @@ -1,61 +0,0 @@ -#date: 2024-12-03T17:02:09Z -#url: https://api.github.com/gists/d66348748e9720ad595700ce83a084c3 -#owner: https://api.github.com/users/adiralashiva8 - -import os -from robot.api.parsing import get_model, ModelVisitor, Token - -class RobotParser(ModelVisitor): - def __init__(self, filepath): - self.filepath = filepath - self.has_smoke_tag = False - - def visit_SettingSection(self, node): - # Check for 'Force Tags' in the settings section - for child in node.body: - "**********" "**********" "**********" "**********" "**********" "**********" "**********" "**********" "**********" "**********" "**********" "**********" "**********"i "**********"f "**********" "**********"c "**********"h "**********"i "**********"l "**********"d "**********". "**********"t "**********"y "**********"p "**********"e "**********" "**********"= "**********"= "**********" "**********"T "**********"o "**********"k "**********"e "**********"n "**********". "**********"F "**********"O "**********"R "**********"C "**********"E "**********"_ "**********"T "**********"A "**********"G "**********"S "**********": "**********" - suite_tags = "**********" - if any("smoke" in tag.lower() for tag in suite_tags): - self.has_smoke_tag = True - return # Exit early if 'smoke' is found - - def visit_TestCase(self, node): - # Check for 'Tags' in the test cases - for section in node.body: - if hasattr(section, "get_value"): - tags = "**********" - if tags and any("smoke" in tag.lower() for tag in tags): - self.has_smoke_tag = True - return # Exit early if 'smoke' is found - - def suite_contains_smoke(self): - return self.has_smoke_tag - - -def get_robot_metadata(filepath): - """Checks if a Robot Framework suite file contains the 'smoke' tag.""" - model = get_model(filepath) - robot_parser = RobotParser(filepath) - robot_parser.visit(model) - return robot_parser.suite_contains_smoke() - - -def fetch_suites_with_smoke_tag(folder): - """Fetches all Robot Framework suite files containing the 'smoke' tag.""" - suites = [] - for root, _, files in os.walk(folder): - for file in files: - if file.lower().endswith(".robot"): - file_path = os.path.join(root, file) - if get_robot_metadata(file_path): - suites.append(file_path) - return suites - - -# Example usage -if __name__ == "__main__": - folder = "SNOW" - suites_with_smoke_tag = fetch_suites_with_smoke_tag(folder) - - for suite in suites_with_smoke_tag: - print(suite) diff --git a/seeker/snippet/go-install.sh b/seeker/snippet/go-install.sh new file mode 100644 index 00000000..3008f64b --- /dev/null +++ b/seeker/snippet/go-install.sh @@ -0,0 +1,15 @@ +#date: 2024-12-05T17:03:46Z +#url: https://api.github.com/gists/d777a3533c5a9ee0a7d3c38c10225f38 +#owner: https://api.github.com/users/hyhecor + +#!/bin/bash +GOVERSION=$( curl https://go.dev/VERSION?m=text | head -n 1 ) +GOROOT=/usr/local/go/bin + +rm -rf /usr/local/go && \ + wget -O - https://go.dev/dl/${GOVERSION}.linux-amd64.tar.gz | \ + tar xz -C /usr/local + +export PATH=$PATH:$GOROOT + +go version \ No newline at end of file diff --git a/seeker/snippet/headline.zsh b/seeker/snippet/headline.zsh index cf95406b..b2f8d787 100644 --- a/seeker/snippet/headline.zsh +++ b/seeker/snippet/headline.zsh @@ -705,7 +705,7 @@ headline-precmd() { # Right prompt if [[ $HL_CLOCK_MODE == 'on' ]]; then - RPROMPT='${HL_CLOCK_TEMPLATE/$HL_TEMPLATE_TOKEN/$(eval ${=HL_CLOCK_SOURCE})}%{$reset%}$HL_RPROMPT' + RPROMPT= "**********"=HL_CLOCK_SOURCE})}%{$reset%}$HL_RPROMPT' else RPROMPT=$HL_RPROMPT fi @@ -713,3 +713,6 @@ headline-precmd() { _HL_CMD_NUM_PREV=$_HL_CMD_NUM _HL_AT_TOP='false' } +$_HL_CMD_NUM + _HL_AT_TOP='false' +} diff --git a/seeker/snippet/lol_worlds_simulator.py b/seeker/snippet/lol_worlds_simulator.py deleted file mode 100644 index ab7d3014..00000000 --- a/seeker/snippet/lol_worlds_simulator.py +++ /dev/null @@ -1,396 +0,0 @@ -#date: 2024-12-03T16:52:15Z -#url: https://api.github.com/gists/6dbf7a20cfedd79134067a2ab22bead8 -#owner: https://api.github.com/users/aureliony - -import multiprocessing -import random -from collections import Counter, defaultdict - -import matplotlib.pyplot as plt - -teams = [ - 'HLE', 'GEN', 'T1', 'DK', - 'BLG', 'TES', 'LNG', 'WBG', - 'G2', 'FNC', - 'FLY', 'TL', - 'MDK', 'GAM', - 'PNG', 'PSG' -] - -elo_ratings_default = { - "GEN": 1663, "BLG": 1602, "HLE": 1572, "TES": 1508, "G2": 1478, "T1": 1467, - "DK": 1445, "LNG": 1407, "WBG": 1391, "FNC": 1372, "TL": 1362, "FLY": 1342, - "PSG": 1323, "MDK": 1302, "GAM": 1254, "PNG": 1183 -} -elo_ratings_default_with_g2_penalty = { - "GEN": 1663, "BLG": 1602, "HLE": 1572, "TES": 1508, "G2": 1391, "T1": 1467, - "DK": 1445, "LNG": 1407, "WBG": 1391, "FNC": 1372, "TL": 1362, "FLY": 1342, - "PSG": 1323, "MDK": 1302, "GAM": 1254, "PNG": 1183 -} -elo_ratings = { - "GEN": 1663, "BLG": 1602, "HLE": 1572, "TES": 1508, "G2": 1391, "T1": 1467, - "DK": 1445, "LNG": 1407, "WBG": 1391, "FNC": 1122, "TL": 1112, "FLY": 1092, - "PSG": 1073, "MDK": 1052, "GAM": 1104, "PNG": 933 -} -# elo_ratings = elo_ratings_default_with_g2_penalty - -def elo_win_probability(team1, team2): - R1 = elo_ratings[team1] - R2 = elo_ratings[team2] - prob_team1_wins = 1 / (1 + 10 ** ((R2 - R1) / 400)) - return prob_team1_wins - - -probs = { - ('HLE', 'GEN') : 0.47, - ('HLE', 'T1') : 0.66, - ('HLE', 'DK') : 0.66, - ('HLE', 'BLG') : 0.45, - ('HLE', 'TES') : 0.5, - ('HLE', 'LNG') : 0.7, - ('HLE', 'WBG') : 0.7, - ('HLE', 'G2') : 0.8, - ('HLE', 'FNC') : 1.0, - ('HLE', 'FLY') : 1.0, - ('HLE', 'TL') : 1.0, - ('HLE', 'MDK') : 1.0, - ('HLE', 'GAM') : 1.0, - ('HLE', 'PNG') : 1.0, - ('HLE', 'PSG') : 0.95, - - ('GEN', 'T1') : 0.77, - ('GEN', 'DK') : 0.75, - ('GEN', 'BLG') : 0.5, - ('GEN', 'TES') : 0.6, - ('GEN', 'LNG') : 0.66, - ('GEN', 'WBG') : 0.7, - ('GEN', 'G2') : 0.8, - ('GEN', 'FNC') : 1.0, - ('GEN', 'FLY') : 1.0, - ('GEN', 'TL') : 1.0, - ('GEN', 'MDK') : 1.0, - ('GEN', 'GAM') : 1.0, - ('GEN', 'PNG') : 1.0, - ('GEN', 'PSG') : 0.95, - - ('T1', 'DK') : 0.6, - ('T1', 'BLG') : 0.5, - ('T1', 'TES') : 0.45, - ('T1', 'LNG') : 0.66, - ('T1', 'WBG') : 0.7, - ('T1', 'G2') : 0.75, - ('T1', 'FNC') : 1.0, - ('T1', 'FLY') : 1.0, - ('T1', 'TL') : 1.0, - ('T1', 'MDK') : 1.0, - ('T1', 'GAM') : 1.0, - ('T1', 'PNG') : 1.0, - ('T1', 'PSG') : 0.9, - - ('DK', 'BLG') : 0.3, - ('DK', 'TES') : 0.3, - ('DK', 'LNG') : 0.3, - ('DK', 'WBG') : 0.5, - ('DK', 'G2') : 0.5, - ('DK', 'FNC') : 1.0, - ('DK', 'FLY') : 1.0, - ('DK', 'TL') : 1.0, - ('DK', 'MDK') : 1.0, - ('DK', 'GAM') : 1.0, - ('DK', 'PNG') : 1.0, - ('DK', 'PSG') : 0.9, - - ('BLG', 'TES') : 0.63, - ('BLG', 'LNG') : 0.75, - ('BLG', 'WBG') : 0.77, - ('BLG', 'G2') : 0.85, - ('BLG', 'FNC') : 1.0, - ('BLG', 'FLY') : 1.0, - ('BLG', 'TL') : 1.0, - ('BLG', 'MDK') : 1.0, - ('BLG', 'GAM') : 1.0, - ('BLG', 'PNG') : 1.0, - ('BLG', 'PSG') : 0.8, - - ('TES', 'LNG') : 0.66, - ('TES', 'WBG') : 0.66, - ('TES', 'G2') : 0.75, - ('TES', 'FNC') : 1.0, - ('TES', 'FLY') : 1.0, - ('TES', 'TL') : 1.0, - ('TES', 'MDK') : 1.0, - ('TES', 'GAM') : 1.0, - ('TES', 'PNG') : 1.0, - ('TES', 'PSG') : 0.8, - - ('LNG', 'WBG') : 0.52, - ('LNG', 'G2') : 0.55, - ('LNG', 'FNC') : 1.0, - ('LNG', 'FLY') : 1.0, - ('LNG', 'TL') : 1.0, - ('LNG', 'MDK') : 1.0, - ('LNG', 'GAM') : 1.0, - ('LNG', 'PNG') : 1.0, - ('LNG', 'PSG') : 0.8, - - ('WBG', 'G2') : 0.42, - ('WBG', 'FNC') : 0.66, - ('WBG', 'FLY') : 0.5, - ('WBG', 'TL') : 0.75, - ('WBG', 'MDK') : 1.0, - ('WBG', 'GAM') : 1.0, - ('WBG', 'PNG') : 1.0, - ('WBG', 'PSG') : 0.8, - - ('G2', 'FNC') : 0.75, - ('G2', 'FLY') : 0.66, - ('G2', 'TL') : 0.75, - ('G2', 'MDK') : 0.9, - ('G2', 'GAM') : 1.0, - ('G2', 'PNG') : 1.0, - ('G2', 'PSG') : 0.7, - - ('FNC', 'FLY') : 0.5, - ('FNC', 'TL') : 0.5, - ('FNC', 'MDK') : 0.62, - ('FNC', 'GAM') : 0.8, - ('FNC', 'PNG') : 1.0, - ('FNC', 'PSG') : 0.58, - - ('FLY', 'TL') : 0.5, - ('FLY', 'MDK') : 0.5, - ('FLY', 'GAM') : 0.7, - ('FLY', 'PNG') : 1.0, - ('FLY', 'PSG') : 0.5, - - ('TL', 'MDK') : 0.5, - ('TL', 'GAM') : 0.7, - ('TL', 'PNG') : 0.9, - ('TL', 'PSG') : 0.5, - - ('MDK', 'GAM') : 0.8, - ('MDK', 'PNG') : 1.0, - ('MDK', 'PSG') : 0.6, - - ('GAM', 'PNG') : 0.5, - ('GAM', 'PSG') : 0.2, - - ('PNG', 'PSG') : 0.0, -} -# probs = {} -# for i in range(len(teams)-1): -# for j in range(i+1, len(teams)): -# team = teams[i] -# team2 = teams[j] -# probs[(team, team2)] = elo_win_probability(team, team2) -# for k,v in probs.items(): -# print(k, ':', v, end=',\n') -# exit() - -for (team1, team2), prob in list(probs.items()): - probs[(team2, team1)] = 1.0 - prob - -def win_probability(team1, team2): - return probs[(team1, team2)] - -# print(win_probability('HLE', 'G2')) -# exit() - -# Function to simulate a match considering Elo ratings -def simulate_match(team1, team2): - prob_team1_wins = win_probability(team1, team2) - # Simulate the match based on probabilities - if random.random() <= prob_team1_wins: - return team1, team2 - else: - return team2, team1 - - -# Function to create matchups for a round based on win-loss records -def create_matchups(team_records, done_matchups): - grouped_teams = defaultdict(list) - for team, record in team_records.items(): - if record['wins'] < 3 and record['losses'] < 3: - key = (record['wins'], record['losses']) - grouped_teams[key].append(team) - - matchups = [] - for record_group, teams in grouped_teams.items(): - assert len(teams) % 2 == 0, \ - "No. of teams in the pool is odd" - - while True: - random.shuffle(teams) - test_matchups = [(teams[i], teams[i+1]) for i in range(0, len(teams), 2)] - if not any(matchups in done_matchups for matchups in test_matchups): - matchups.extend(test_matchups) - break - - return matchups - - -# Function to simulate a round of matches -def simulate_round(matchups, team_records): - for match in matchups: - winner, loser = simulate_match(match[0], match[1]) - team_records[winner]['wins'] += 1 - team_records[loser]['losses'] += 1 - - -# Function to check if the tournament should continue -def tournament_active(team_records): - return any(record['wins'] < 3 and record['losses'] < 3 for record in team_records.values()) - - -# Function to run simulations -def run_simulations(n): - outcomes = Counter() - - for _ in range(n): - team_records = { - "HLE": {"wins": 3, "losses": 1}, - "GEN": {"wins": 3, "losses": 0}, - "T1": {"wins": 3, "losses": 1}, - "DK": {"wins": 2, "losses": 2}, - - "BLG": {"wins": 2, "losses": 2}, - "TES": {"wins": 3, "losses": 1}, - "LNG": {"wins": 3, "losses": 0}, - "WBG": {"wins": 2, "losses": 2}, - - "G2": {"wins": 2, "losses": 2}, - "FNC": {"wins": 1, "losses": 3}, - "FLY": {"wins": 2, "losses": 2}, - "TL": {"wins": 2, "losses": 2}, - - "MDK": {"wins": 0, "losses": 3}, - "GAM": {"wins": 1, "losses": 3}, - "PNG": {"wins": 0, "losses": 3}, - "PSG": {"wins": 1, "losses": 3}, - } - - done_matchups = [ - ('MDK', 'BLG'), - ('TES', 'T1'), - ('GEN', 'WBG'), - ('FNC', 'DK'), - ('TL', 'LNG'), - ('PSG', 'HLE'), - ('FLY', 'GAM'), - ('PNG', 'G2'), - - ('G2', 'HLE'), - ('DK', 'FLY'), - ('GEN', 'TES'), - ('BLG', 'LNG'), - ('T1', 'PNG'), - ('PSG', 'MDK'), - ('WBG', 'TL'), - ('FNC', 'GAM'), - - ('DK', 'LNG'), - ('HLE', 'GEN'), - ('TES', 'FNC'), - ('BLG', 'T1'), - ('PSG', 'FLY'), - ('WBG', 'G2'), - ('MDK', 'GAM'), - ('PNG', 'TL'), - - ('DK', 'TES'), - ('HLE', 'FLY'), - ('G2', 'T1'), - ('BLG', 'PSG'), - ('WBG', 'FNC'), - ('TL', 'GAM'), - ] - - current_matchups = [ - ('BLG', 'G2'), - ('TL', 'FLY'), - ('DK', 'WBG'), - ] - - # current_matchups = done_matchups - # done_matchups = [] - # for k in team_records: - # team_records[k]['wins'] = 0 - # team_records[k]['losses'] = 0 - - # Simulate the current round - simulate_round(current_matchups, team_records) - done_matchups.extend(current_matchups) - # Continue playing rounds until each team has 3 wins or 3 losses - while tournament_active(team_records): - current_matchups = create_matchups(team_records, done_matchups) - simulate_round(current_matchups, team_records) - done_matchups.extend(current_matchups) - - # Count teams that achieved 3 wins - teams_that_got_out = [] - for team, record in team_records.items(): - assert 0 <= record['wins'] <= 3 - assert 0 <= record['losses'] <= 3 - assert record['wins'] == 3 or record['losses'] == 3 - if record['wins'] == 3: - teams_that_got_out.append(team) - - teams_that_got_out.sort(key=lambda team: teams.index(team)) - outcomes[tuple(teams_that_got_out)] += 1 - - return outcomes - - -def plot_histogram(data: dict, top_k=20): - # Extracting keys (items) and values (counts) - items = [(', '.join(outcome), count) for outcome, count in data.items()] - items.sort(key=lambda x: x[1], reverse=True) - outcomes, counts = zip(*items) - total = sum(counts) - probs = [count / total for count in counts] - print(sum(probs[:top_k]), flush=True) - - # Plotting the bar chart - plt.figure(figsize=(top_k*0.4, 8)) - plt.bar(outcomes[:top_k], probs[:top_k], color='skyblue') - - # Adding labels and title - plt.xlabel('Swiss outcome') - plt.ylabel('Probability') - - # Rotating the x labels for better readability - plt.xticks(rotation=90) - - # Display the plot - plt.tight_layout() - plt.show() - - -if __name__ == "__main__": - # Run the simulations and print the probabilities - num_simulations_per_worker = 10000 - num_workers = max(1, multiprocessing.cpu_count() - 2) - num_simulations = num_simulations_per_worker * num_workers - numbers = [num_simulations_per_worker] * num_workers - - with multiprocessing.Pool(processes=num_workers) as pool: - list_of_outcomes = pool.map(run_simulations, numbers) - - outcomes = sum(list_of_outcomes, start=Counter()) - - probabilities = Counter() - for team in teams: - probabilities[team] = 0 - for teams, count in outcomes.items(): - for team in teams: - probabilities[team] += count - for team in probabilities: - probabilities[team] /= num_simulations - - # Display the probabilities - print(f"Probability of each team making it out ({num_simulations} simulations):") - for team, prob in sorted(probabilities.items(), key=lambda x: x[1], reverse=True): - print(f"{team}: {prob:.2%}") - print(flush=True) - - plot_histogram(outcomes) diff --git a/seeker/snippet/modbusserver.py b/seeker/snippet/modbusserver.py new file mode 100644 index 00000000..bfeaee91 --- /dev/null +++ b/seeker/snippet/modbusserver.py @@ -0,0 +1,131 @@ +#date: 2024-12-05T17:02:41Z +#url: https://api.github.com/gists/276d9d4183df0e6b3431dcc49a6adbcd +#owner: https://api.github.com/users/fl-kmarston + +#!/usr/bin/env python3 + +import sys +import os +import logging +import argparse +import time + +from threading import current_thread, Thread, Lock +from twisted.internet import reactor + +# pymodbus~=2.5.3 +from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext +from pymodbus.datastore import ModbusSparseDataBlock +from pymodbus.server.asynchronous import StartTcpServer + +from random import randrange + +# Function to set logging level for all loggers +def set_logging_level(level): + loggers = [logging.getLogger(name) for name in logging.root.manager.loggerDict] + for logger in loggers: + if logger.name.startswith("pyModbus"): + continue + if logger.name.startswith("pymodbus"): + continue + if logger.name.startswith("asyncio"): + continue + if logger.name.startswith("concurrent"): + continue + logger.setLevel(level) + + +class SimulateModbusUnit(ModbusSlaveContext): + + def __init__(self, *args, **kwargs): + ''' + 'di' - Discrete Inputs initializer + 'co' - Coils initializer + 'hr' - Holding Register initializer + 'ir' - Input Registers iniatializer + + zero_mode + ''' + super().__init__(*args, **kwargs) + self._dataLock = Lock() + self._IModbusSlaveContext__fx_mapper['di'] = 'd' + self._IModbusSlaveContext__fx_mapper['co'] = 'c' + self._IModbusSlaveContext__fx_mapper['hr'] = 'h' + self._IModbusSlaveContext__fx_mapper['ir'] = 'i' + self._IModbusSlaveContext__fx_mapper['d'] = 'd' + self._IModbusSlaveContext__fx_mapper['c'] = 'c' + self._IModbusSlaveContext__fx_mapper['h'] = 'h' + self._IModbusSlaveContext__fx_mapper['i'] = 'i' + + def setValues(self, fx, address, values): + '''Make SetValues Thread safe, + Add hr,co,di,''' + print("setValues", fx, address, values) + with self._dataLock: + return super().setValues(fx, address, values) + + def loop(self): + while reactor.running: + _loop_start = time.time() + wait = randrange(5) + 1 + # print(f"Delay: {current_thread().name} {wait}") + time.sleep(wait) + diff = time.time() - _loop_start -wait + print(f"{diff:0.3f} Done: {current_thread().name} Wait: {wait}") + time.sleep(POLL_INTERVAL) + + +if __name__ == "__main__": + + FORMAT = ( + "%(threadName)-11s" " %(levelname)-8s %(module)-12s:%(lineno)-5s %(message)s" + ) + logging.basicConfig(format=FORMAT) + level = os.getenv("LOGLEVEL", "WARNING") + + print(f"LOGLEVEL={level}") + set_logging_level(level) + + log.warning("warning...") + log.info("info...") + log.debug("debug...") + + args = parse_args() + log.info("Passed args: {}".format(args)) + + addr = args.local + host, port = addr.split(":") + port = int(port) + + hr1 = ModbusSparseDataBlock(values={0: [12] * 20, 4090: [13] * 95}) + unit1 = SimulateModbusUnit(hr=hr1, zero_mode=True) # Keep it consistent! + + # hr2 = ModbusSparseDataBlock(values={0: [12] * 20, 4090: [13] * 95}) + unit2 = SimulateModbusUnit(zero_mode=True) # Keep it consistent! + + the_loopers = [ + unit1.loop, + unit2.loop, + ] + + def reactor_loop(unit_loops): + threads = [] + for loop in unit_loops: + + threads.append( + Thread( + target=loop, + ) # name=f"poll_cycle({cube.name})") + ) + for thread in threads: + thread.start() + print("ALL STARTED...") + return + + reactor.callInThread(reactor_loop, the_loopers) + context_server = ModbusServerContext(slaves={1: unit1, 2: unit2}, single=False) + StartTcpServer( + context=context_server, + address=(host, port), + # framer=MyFramer, + ) diff --git a/seeker/snippet/mount_vbox_shared_folder.sh b/seeker/snippet/mount_vbox_shared_folder.sh new file mode 100644 index 00000000..26577d9c --- /dev/null +++ b/seeker/snippet/mount_vbox_shared_folder.sh @@ -0,0 +1,10 @@ +#date: 2024-12-05T17:12:02Z +#url: https://api.github.com/gists/5cc903d166dcdc0cc7c545608454ec28 +#owner: https://api.github.com/users/jcrtexidor + +# ~/.cmd/mount_vbox_shared_folder.sh + +mkdir -p /media/shared_folder +if [ $(mount | grep -q "shared_folder") ]; then + mount -t vboxsf shared_folder /media/shared_folder +fi diff --git a/seeker/snippet/ola.py b/seeker/snippet/ola.py deleted file mode 100644 index 8ae797ed..00000000 --- a/seeker/snippet/ola.py +++ /dev/null @@ -1,128 +0,0 @@ -#date: 2024-12-03T17:13:01Z -#url: https://api.github.com/gists/457f707a8ae41d5674a93ce62a820785 -#owner: https://api.github.com/users/RajChowdhury240 - -import boto3 -import csv -import threading -from concurrent.futures import ThreadPoolExecutor -from rich.progress import Progress -from rich.table import Table -from rich.console import Console - -console = Console() - -output_file = "ta-ca-roles-info.csv" -role_prefixes = ["ta-", "ca-"] - -def assume_role(account_id, role_name): - sts_client = boto3.client("sts") - try: - response = sts_client.assume_role( - RoleArn=f"arn:aws:iam::{account_id}:role/{role_name}", - RoleSessionName="TrustRelationshipAnalysis" - ) - credentials = response["Credentials"] - return boto3.client( - "iam", - aws_access_key_id= "**********" - aws_secret_access_key= "**********" - aws_session_token= "**********" - ) - except Exception as e: - console.print(f"[red]Failed to assume role in account {account_id}: {e}") - return None - -def list_roles(client): - roles = [] - try: - paginator = client.get_paginator("list_roles") - for page in paginator.paginate(): - roles.extend(page["Roles"]) - except Exception as e: - console.print(f"[red]Error listing roles: {e}") - return roles - -def analyze_trust_relationships(account_id, account_name, iam_client, result_lock, results): - roles = list_roles(iam_client) - ta_roles = [role for role in roles if role["RoleName"].startswith("ta-")] - ca_roles = [role for role in roles if role["RoleName"].startswith("ca-")] - - for ca_role in ca_roles: - ca_role_name = ca_role["RoleName"] - trust_policy = ca_role.get("AssumeRolePolicyDocument", {}) - for statement in trust_policy.get("Statement", []): - if statement.get("Effect") == "Allow": - principals = statement.get("Principal", {}) - aws_principals = principals.get("AWS", []) - if not isinstance(aws_principals, list): - aws_principals = [aws_principals] - - for principal in aws_principals: - if principal.startswith(f"arn:aws:iam::{account_id}:role/ta-"): - with result_lock: - results.append([ - account_id, - account_name, - principal.split("/")[-1], - ca_role_name, - str(statement), - ]) - -def get_all_accounts(): - org_client = boto3.client("organizations") - accounts = [] - try: - paginator = org_client.get_paginator("list_accounts") - for page in paginator.paginate(): - accounts.extend(page["Accounts"]) - except Exception as e: - console.print(f"[red]Error fetching accounts: {e}") - return accounts - -def main(): - accounts = get_all_accounts() - results = [] - result_lock = threading.Lock() - - with open(output_file, "w", newline="") as csvfile: - csv_writer = csv.writer(csvfile) - csv_writer.writerow(["AccountID", "AccountName", "RoleName-With-Ta", "RoleName-With-Ca", "Trust relationship reference"]) - - with Progress() as progress: - task = progress.add_task("Analyzing roles...", total=len(accounts)) - - def process_account(account): - account_id = account["Id"] - account_name = account["Name"] - iam_client = assume_role(account_id, "ca-iam-cie-engineer") - if iam_client: - analyze_trust_relationships(account_id, account_name, iam_client, result_lock, results) - progress.update(task, advance=1) - - with ThreadPoolExecutor(max_workers=10) as executor: - for account in accounts: - executor.submit(process_account, account) - - with open(output_file, "a", newline="") as csvfile: - csv_writer = csv.writer(csvfile) - csv_writer.writerows(results) - - table = Table(title="Trust Relationships") - table.add_column("AccountID") - table.add_column("AccountName") - table.add_column("RoleName-With-Ta") - table.add_column("RoleName-With-Ca") - table.add_column("Trust relationship reference") - - for result in results: - table.add_row(*result) - - console.print(table) - -if __name__ == "__main__": - main() -(table) - -if __name__ == "__main__": - main() diff --git a/seeker/snippet/read_csv_with_pandas.py b/seeker/snippet/read_csv_with_pandas.py deleted file mode 100644 index 84dc6531..00000000 --- a/seeker/snippet/read_csv_with_pandas.py +++ /dev/null @@ -1,11 +0,0 @@ -#date: 2024-12-03T16:54:29Z -#url: https://api.github.com/gists/e43680d58c2c5d032ad46b41f2d9ee53 -#owner: https://api.github.com/users/KeichiTS - -## Read *.csv with pandas ## - -#import pandas library -import pandas as pd - -#By default, sep = ',' and header = 0 -df = pd.read_csv('archive.csv', sep = ';', header = 1) \ No newline at end of file diff --git a/seeker/snippet/reset-foundry-version-to-monorepo.sh b/seeker/snippet/reset-foundry-version-to-monorepo.sh deleted file mode 100644 index 99659007..00000000 --- a/seeker/snippet/reset-foundry-version-to-monorepo.sh +++ /dev/null @@ -1,38 +0,0 @@ -#date: 2024-12-03T16:55:41Z -#url: https://api.github.com/gists/54ff275b32482823029816d9f1e29a9c -#owner: https://api.github.com/users/blmalone - -resetFoundryVersion() { - local TOML_URL="https://raw.githubusercontent.com/ethereum-optimism/optimism/refs/heads/develop/mise.toml" - - local TOML_FILE="/tmp/mise.toml" - curl -s -o "$TOML_FILE" "$TOML_URL" - - if [[ ! -f "$TOML_FILE" ]]; then - echo "Failed to download the TOML file." - return 1 - fi - - if command -v yq &>/dev/null; then - local forge_version=$(yq e '.tools.forge' "$TOML_FILE") - else - echo "yq is not installed. Install it by running: brew install yq" - return 1 - fi - - if [[ -z "$forge_version" ]]; then - echo "Failed to extract the forge version from the TOML file." - return 1 - fi - - echo "Forge version: $forge_version" - - foundryup -C "$forge_version" - - if [[ $? -ne 0 ]]; then - echo "Failed to run the foundryup command." - return 1 - fi - - echo "Foundry updated successfully with version: $forge_version" -} \ No newline at end of file diff --git a/seeker/snippet/run1 b/seeker/snippet/run1 new file mode 100644 index 00000000..d27d285d --- /dev/null +++ b/seeker/snippet/run1 @@ -0,0 +1,20 @@ +#date: 2024-12-05T17:13:33Z +#url: https://api.github.com/gists/53acc37604c9a6eb4fba1fc09544465b +#owner: https://api.github.com/users/livecode-bot + +#!/bin/bash +set -e -v + +### PICK VERSION +export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 +export PATH=$JAVA_HOME/bin:$PATH + +### CHECK VERSION +java -version + +### COMPILE +cat $1 >Unsound.java +javac Unsound.java + +### RUN +java Unsound diff --git a/seeker/snippet/ssh_hole.sh b/seeker/snippet/ssh_hole.sh deleted file mode 100644 index d5191180..00000000 --- a/seeker/snippet/ssh_hole.sh +++ /dev/null @@ -1,55 +0,0 @@ -#date: 2024-12-03T17:00:12Z -#url: https://api.github.com/gists/2547efcaf6f73958d3eb125da12f6a9b -#owner: https://api.github.com/users/ayasechan - -#!/bin/bash - -# 检查是否以 root 身份运行 - -if [[ $EUID -ne 0 ]]; then - - echo "此脚本需要以 root 身份运行。" exit 1 - -fi - -# 配置 - -SET_NAME="blocked_ips" # ipset 集合名称 - -PORT=22 # 监听的端口 - -# 初始化 ipset 集合 - -if ! ipset list "$SET_NAME" &>/dev/null; then - - echo "创建 ipset 集合 $SET_NAME..." - - ipset create "$SET_NAME" hash:ip - - iptables -A INPUT -m set --match-set "$SET_NAME" src -j DROP - -fi - -echo "开始监听 22 端口的连接..." - -# 使用 nc 监听端口 - -while true; do - - # 提取连接的 IP 地址 - - IP=$(nc -v -l -p $PORT 2>&1 >/dev/null | grep -oP '^\d[^\:]+') - - echo "检测到连接,源 IP: $IP" - - if [[ -n "$IP" ]]; then - - echo "屏蔽 IP 地址 $IP..." - - # 添加到 ipset 并记录 - - ipset add "$SET_NAME" "$IP" - - fi - -done \ No newline at end of file diff --git a/seeker/snippet/yaml_merger.py b/seeker/snippet/yaml_merger.py new file mode 100644 index 00000000..4459c5e5 --- /dev/null +++ b/seeker/snippet/yaml_merger.py @@ -0,0 +1,112 @@ +#date: 2024-12-05T17:03:51Z +#url: https://api.github.com/gists/2d21dab285a18e838bc74ce3a35fa593 +#owner: https://api.github.com/users/vlad-dh + +# TODO: Move to proper place and add to git workflow + +import yaml +import argparse +from typing import Dict, Any +from copy import deepcopy +from pathlib import Path + + +def deep_update(base_dict: Dict[str, Any], update_dict: Dict[str, Any]) -> Dict[str, Any]: + """ + Recursively update a nested dictionary structure with another dictionary. + Args: + base_dict: The original dictionary to be updated + update_dict: The dictionary containing override values + Returns: + Updated dictionary with merged values + """ + result = deepcopy(base_dict) + + for key, value in update_dict.items(): + if isinstance(value, dict) and key in result and isinstance(result[key], dict): + # If both values are dictionaries, recurse + result[key] = deep_update(result[key], value) + else: + # Otherwise, override the value + result[key] = deepcopy(value) + + return result + + +def merge_yaml_files(base_file: str, override_file: str, output_file: str = None) -> Dict[str, Any]: + """ + Merge two YAML files where the override file takes precedence. + Args: + base_file: Path to the base YAML file with the complete structure + override_file: Path to the YAML file containing override values + output_file: Optional path to save the merged YAML + Returns: + Merged dictionary + """ + try: + # Load base file + with open(base_file, 'r') as f: + base_config = yaml.safe_load(f) + + # Load override file + with open(override_file, 'r') as f: + override_config = yaml.safe_load(f) + + if not isinstance(base_config, dict): + raise ValueError("Base YAML must be a dictionary") + if not isinstance(override_config, dict): + raise ValueError("Override YAML must be a dictionary") + + # Merge the configurations + merged_config = deep_update(base_config, override_config) + + # Save to output file if specified + if output_file: + with open(output_file, 'w') as f: + yaml.dump(merged_config, f, default_flow_style=False, sort_keys=False) + + return merged_config + + except yaml.YAMLError as e: + raise ValueError(f"Error parsing YAML: {str(e)}") + except Exception as e: + raise Exception(f"Error processing files: {str(e)}") + + +def main(): + parser = argparse.ArgumentParser( + description='Merge two YAML files, where the second file overrides values from the first file.' + ) + parser.add_argument('base_file', type=str, help='Path to the base YAML file with the complete structure') + parser.add_argument('override_file', type=str, help='Path to the YAML file containing override values') + parser.add_argument('-o', '--output', type=str, help='Output file path (optional, defaults to merged_output.yaml)', + default='merged_output.yaml') + parser.add_argument('--print', action='store_true', help='Print the merged YAML to stdout') + + args = parser.parse_args() + + # Validate file paths + if not Path(args.base_file).exists(): + print(f"Error: Base file '{args.base_file}' does not exist") + return 1 + if not Path(args.override_file).exists(): + print(f"Error: Override file '{args.override_file}' does not exist") + return 1 + + try: + merged = merge_yaml_files(args.base_file, args.override_file, args.output) + print(f"Successfully merged YAML files. Result saved to {args.output}") + + if args.print: + print("\nMerged YAML content:") + print(yaml.dump(merged, default_flow_style=False, sort_keys=False)) + + return 0 + + except Exception as e: + print(f"Error: {str(e)}") + return 1 + + +if __name__ == "__main__": + exit(main()) \ No newline at end of file