kahoot-to-anki 1.0.0__tar.gz → 1.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,78 @@
1
+ Metadata-Version: 2.4
2
+ Name: kahoot-to-anki
3
+ Version: 1.1.0
4
+ Summary: CLI tool to convert Kahoot quiz reports into Anki flashcards
5
+ Author: Simon Hardmeier
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: genanki
11
+ Requires-Dist: pandas
12
+ Requires-Dist: openpyxl
13
+ Dynamic: license-file
14
+
15
+ # kahoot-to-anki
16
+ [![Python](https://img.shields.io/badge/python-3.9+-blue.svg)](#installation)
17
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
18
+
19
+ <br>
20
+
21
+ **kahoot-to-anki** is a command‑line tool that converts exported Kahoot quiz reports (Excel Files) into Anki flashcard decks (.apkg format).<br>
22
+ Designed for educators, students, and any self-learners to easily turn quiz results into effective spaced‑repetition decks.
23
+
24
+ ## Installation & Usage
25
+ ### Option 1: Install via pip
26
+ ```
27
+ pip install kahoot-to-anki
28
+ ```
29
+ Then run:
30
+ ```
31
+ kahoot-to-anki --help
32
+ ```
33
+ Example: Process all Kahoot Exports in the `./exports/` folder and write the flashcard deck and CSV file to `./data/`:
34
+ ```
35
+ kahoot-to-anki --inp "./exports" --out "./data" --csv
36
+ ```
37
+
38
+ ### Option 2: Run with Docker
39
+ ```
40
+ # Clone Repository
41
+ git clone https://github.com/SimonHRD/kahoot-to-anki.git
42
+
43
+ # Move into Repository
44
+ cd kahoot-to-anki
45
+
46
+ # Build docker image with the kahoot-to-anki tag
47
+ docker build -t kahoot-to-anki .
48
+
49
+ # Check help command
50
+ docker run --rm kahoot-to-anki --help
51
+
52
+ # Run with local data
53
+ docker run --rm -v "$(pwd)/data:/app/data" kahoot-to-anki --out "./data" --csv
54
+ ```
55
+
56
+ On PowerShell:
57
+ ```
58
+ docker run --rm -v ${PWD}\data:/app/data kahoot-to-anki --out "./data" --csv
59
+ ```
60
+
61
+ ## CLI Arguments
62
+ You can provide either a single Kahoot Excel file or a directory containing multiple `.xlsx` files as input.<br>
63
+ All valid Excel files in the directory will be processed.
64
+
65
+ | Argument | Description |
66
+ |----------------------|--------------------------------------------------------------------------------|
67
+ | `-i`, `--inp` | Path to the input Excel file or directory (default: `./data`) |
68
+ | `-o`, `--out` | Path to the output directory for the Anki deck (default: `./`) |
69
+ | `--sheet` | The Excel Sheet with the raw Kahoot quiz data (default: `RawReportData Data`) |
70
+ | `--csv`, `--no-csv` | Enable or disable CSV export of the questions (default: disabled) |
71
+ | `-t`, `--title` | Title of the generated Anki deck (default: `"Kahoot"`) |
72
+
73
+
74
+ ## Example
75
+ An example Kahoot export file is available in `data/`. The generated deck will be saved as `anki.apkg` in the specified `--out` directory (default: `./`).
76
+
77
+ ## License
78
+ MIT — see [LICENSE](./LICENSE)
@@ -0,0 +1,64 @@
1
+ # kahoot-to-anki
2
+ [![Python](https://img.shields.io/badge/python-3.9+-blue.svg)](#installation)
3
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
4
+
5
+ <br>
6
+
7
+ **kahoot-to-anki** is a command‑line tool that converts exported Kahoot quiz reports (Excel Files) into Anki flashcard decks (.apkg format).<br>
8
+ Designed for educators, students, and any self-learners to easily turn quiz results into effective spaced‑repetition decks.
9
+
10
+ ## Installation & Usage
11
+ ### Option 1: Install via pip
12
+ ```
13
+ pip install kahoot-to-anki
14
+ ```
15
+ Then run:
16
+ ```
17
+ kahoot-to-anki --help
18
+ ```
19
+ Example: Process all Kahoot Exports in the `./exports/` folder and write the flashcard deck and CSV file to `./data/`:
20
+ ```
21
+ kahoot-to-anki --inp "./exports" --out "./data" --csv
22
+ ```
23
+
24
+ ### Option 2: Run with Docker
25
+ ```
26
+ # Clone Repository
27
+ git clone https://github.com/SimonHRD/kahoot-to-anki.git
28
+
29
+ # Move into Repository
30
+ cd kahoot-to-anki
31
+
32
+ # Build docker image with the kahoot-to-anki tag
33
+ docker build -t kahoot-to-anki .
34
+
35
+ # Check help command
36
+ docker run --rm kahoot-to-anki --help
37
+
38
+ # Run with local data
39
+ docker run --rm -v "$(pwd)/data:/app/data" kahoot-to-anki --out "./data" --csv
40
+ ```
41
+
42
+ On PowerShell:
43
+ ```
44
+ docker run --rm -v ${PWD}\data:/app/data kahoot-to-anki --out "./data" --csv
45
+ ```
46
+
47
+ ## CLI Arguments
48
+ You can provide either a single Kahoot Excel file or a directory containing multiple `.xlsx` files as input.<br>
49
+ All valid Excel files in the directory will be processed.
50
+
51
+ | Argument | Description |
52
+ |----------------------|--------------------------------------------------------------------------------|
53
+ | `-i`, `--inp` | Path to the input Excel file or directory (default: `./data`) |
54
+ | `-o`, `--out` | Path to the output directory for the Anki deck (default: `./`) |
55
+ | `--sheet` | The Excel Sheet with the raw Kahoot quiz data (default: `RawReportData Data`) |
56
+ | `--csv`, `--no-csv` | Enable or disable CSV export of the questions (default: disabled) |
57
+ | `-t`, `--title` | Title of the generated Anki deck (default: `"Kahoot"`) |
58
+
59
+
60
+ ## Example
61
+ An example Kahoot export file is available in `data/`. The generated deck will be saved as `anki.apkg` in the specified `--out` directory (default: `./`).
62
+
63
+ ## License
64
+ MIT — see [LICENSE](./LICENSE)
@@ -0,0 +1 @@
1
+ __version__ = "1.1.0"
@@ -0,0 +1,118 @@
1
+ # Standard library imports
2
+ import argparse
3
+ from dataclasses import dataclass
4
+ import logging
5
+ import os
6
+ import glob
7
+
8
+ # Constants
9
+ DEFAULT_INPUT_DIRECTORY = "./data"
10
+ DEFAULT_OUTPUT_DIRECTORY = "./"
11
+ DEFAULT_DECK_TITLE = "Kahoot"
12
+ KAHOOT_EXCEL_SHEET_NAME_RAW_DATA = "RawReportData Data"
13
+
14
+ # Dataclass to hold CLI arguments
15
+ @dataclass
16
+ class CLIArgs:
17
+ input_path: str
18
+ output_path: str
19
+ sheet: str
20
+ export_csv: bool
21
+ deck_title: str
22
+
23
+
24
+ def get_commandline_arguments() -> CLIArgs:
25
+ """
26
+ Parses the command line arguments and returns a CLIArgs dataclass instance.
27
+
28
+ :return: A CLIArgs dataclass instance
29
+ :rtype: CLIArgs
30
+ """
31
+ parser = argparse.ArgumentParser(description="Create Anki Deck from Kahoot answer")
32
+ parser.add_argument(
33
+ "-i",
34
+ "--inp",
35
+ default=DEFAULT_INPUT_DIRECTORY,
36
+ help=f"Path to the directory containing input Excel files or a single input Excel file. If a directory is "
37
+ f"provided, all Excel files in the directory will be processed. Default: {DEFAULT_INPUT_DIRECTORY}",
38
+ type=str,
39
+ )
40
+ parser.add_argument(
41
+ "-o",
42
+ "--out",
43
+ default=DEFAULT_OUTPUT_DIRECTORY,
44
+ help="Path to the directory where the Anki flashcards package will be generated. "
45
+ "If not specified, the package will be created in the current working directory.",
46
+ type=str,
47
+ )
48
+ parser.add_argument(
49
+ "--sheet",
50
+ default=KAHOOT_EXCEL_SHEET_NAME_RAW_DATA,
51
+ help=f"The Excel Sheet Name with the Kahoot Raw Data. Default {KAHOOT_EXCEL_SHEET_NAME_RAW_DATA}",
52
+ type=str,
53
+ )
54
+ parser.add_argument(
55
+ "--csv",
56
+ action=argparse.BooleanOptionalAction,
57
+ default=False,
58
+ help="Enable or disable CSV export of question data (default: disabled).",
59
+ )
60
+ parser.add_argument(
61
+ "-t",
62
+ "--title",
63
+ default=DEFAULT_DECK_TITLE,
64
+ help="Name of the Anki deck to be created. "
65
+ f"If not specified, the default deck name '{DEFAULT_DECK_TITLE}' will be used.",
66
+ type=str,
67
+ )
68
+ args = parser.parse_args()
69
+
70
+ return CLIArgs(
71
+ input_path=os.path.abspath(args.inp),
72
+ output_path=os.path.abspath(args.out),
73
+ sheet=args.sheet,
74
+ export_csv=args.csv,
75
+ deck_title=args.title
76
+ )
77
+
78
+
79
+ def validation(input_directory: str, output_directory: str) -> None:
80
+ """
81
+ This function validates the command line arguments, checking if the input path is a valid Excel file or directory
82
+ and if the output path is a valid directory.
83
+ The input path needs to be an Excel file or a directory that contains Excel files.
84
+ The output path needs to be a directory and not a file.
85
+
86
+ :param input_directory: The path of the input Excel or directory
87
+ :param output_directory: The path of the output directory
88
+ :return: None
89
+ :rtype: None
90
+ """
91
+ # Check if input is a file
92
+ if not os.path.exists(input_directory):
93
+ logging.error(f"Input directory {input_directory} does not exist!")
94
+ raise FileNotFoundError(f"Input directory {input_directory} does not exist!")
95
+ elif (
96
+ os.path.isfile(input_directory)
97
+ and os.path.splitext(input_directory)[-1] != ".xlsx"
98
+ ):
99
+ logging.error("Input file is not an excel file!")
100
+ raise ValueError("Input file is not an excel file!")
101
+ elif os.path.isdir(input_directory):
102
+ input_excels = os.path.join(input_directory, "*.xlsx")
103
+ if not glob.glob(input_excels):
104
+ logging.error("Input directory does not contain any excel files!")
105
+ raise FileNotFoundError("Input directory does not contain any excel files!")
106
+
107
+ # Check output directory and create when not existing
108
+ if not os.path.isdir(output_directory):
109
+ logging.error("Output is not a directory!")
110
+ raise ValueError("Output is not a directory!")
111
+ if not os.path.exists(output_directory):
112
+ try:
113
+ os.makedirs(output_directory)
114
+ except OSError as e:
115
+ logging.error(
116
+ "Failed to create output directory '%s': %s", output_directory, str(e)
117
+ )
118
+ raise
@@ -0,0 +1,40 @@
1
+ import os
2
+ import logging
3
+ import sys
4
+
5
+ from kahoot_to_anki.cli import get_commandline_arguments, validation
6
+ from kahoot_to_anki.processing import get_questions, make_anki
7
+
8
+ # Configure logging settings
9
+ logging.basicConfig(level=logging.INFO)
10
+
11
+
12
+ def main() -> None:
13
+ # Check command line arguments
14
+ args = get_commandline_arguments()
15
+
16
+ validation(args.input_path, args.output_path)
17
+
18
+ df = get_questions(input_directory=args.input_path, sheet_name=args.sheet)
19
+
20
+ if df.empty:
21
+ logging.warning("No Kahoot questions found to process. Exiting.")
22
+ sys.exit(0)
23
+
24
+ if args.export_csv:
25
+ df.to_csv(
26
+ os.path.join(args.output_path, "kahoot.csv"),
27
+ sep=";",
28
+ index=False,
29
+ encoding="utf-8-sig",
30
+ )
31
+
32
+ make_anki(df, args.output_path, args.deck_title)
33
+
34
+
35
+ if __name__ == "__main__":
36
+ main()
37
+
38
+
39
+
40
+
@@ -0,0 +1,141 @@
1
+ # Standard library imports
2
+ import logging
3
+ import os
4
+ import glob
5
+ from typing import Iterator, Optional
6
+
7
+ # Third-party library imports
8
+ import genanki
9
+ import pandas as pd
10
+
11
+
12
+ def get_questions(input_directory: str, sheet_name: str) -> pd.DataFrame:
13
+ """
14
+ Extracts all the kahoot questions out of the Excel file(s)
15
+
16
+ :param input_directory: The path to the input directory or Excel file
17
+ :param sheet_name: The Excel sheet name with the Kahoot Answers
18
+ :return: All the questions with the possible answers and the solution
19
+ :rtype: pd.DataFrame
20
+ """
21
+
22
+ out = pd.DataFrame(columns=["Question", "Possible Answers", "Correct Answers"])
23
+
24
+ questions_cnt = 0
25
+ files_cnt = 0
26
+
27
+ for file in get_excels(input_directory):
28
+ df = get_excel_data(excel_file=file, sheet_name=sheet_name)
29
+ if df is None:
30
+ continue
31
+ files_cnt += 1
32
+
33
+ df = df_processing(df)
34
+
35
+ # add to out dataframe
36
+ out = pd.concat([out, df], axis=0, ignore_index=True)
37
+
38
+ questions_cnt += len(df)
39
+
40
+ logging.info("Read input files: %d", files_cnt)
41
+ logging.info("Read questions: %d", questions_cnt)
42
+ out = out.drop_duplicates(subset=["Question"])
43
+ return out
44
+
45
+
46
+ def get_excels(path: str) -> Iterator[str]:
47
+ """
48
+ Returns a generator with all Excel files in the given path.
49
+ :param path: the path to an Excel file or a directory with Excel files
50
+ :return: a generator of Excel file paths
51
+ """
52
+ if os.path.isfile(path):
53
+ yield path
54
+ else:
55
+ yield from glob.glob(os.path.join(path, "*.xlsx"))
56
+
57
+
58
+ def get_excel_data(excel_file: str, sheet_name:str) -> Optional[pd.DataFrame]:
59
+ """
60
+ Returns a pd.DataFrame with the kahoot raw data
61
+ :param excel_file: an Excel file with Kahoot raw data
62
+ :param sheet_name: the Excel sheet name with the Kahoot answers
63
+ :return: a DataFrame with the data
64
+ """
65
+ try:
66
+ # read file
67
+ return pd.read_excel(
68
+ excel_file, sheet_name=sheet_name
69
+ )
70
+ except ValueError:
71
+ logging.warning(
72
+ "Skipping file '%s' as it is not a valid Excel file.", excel_file
73
+ )
74
+ return None
75
+ except Exception as e:
76
+ logging.error("Failed to read file '%s': %s", excel_file, str(e))
77
+ return None
78
+
79
+
80
+ def df_processing(data: pd.DataFrame) -> pd.DataFrame:
81
+ """
82
+ Processes the Kahoot question data.
83
+ :param data: DataFrame with Kahoot question data
84
+ :return: Processed DataFrame
85
+ """
86
+ # delete duplicated questions
87
+ data = data.drop_duplicates(subset=["Question Number"])
88
+
89
+ data = data.fillna("")
90
+
91
+ data["Possible Answers"] = data[
92
+ ["Answer 1", "Answer 2", "Answer 3", "Answer 4", "Answer 5", "Answer 6"]
93
+ ].agg("<br>".join, axis=1)
94
+
95
+ # keep only needed columns
96
+ data = data[["Question", "Possible Answers", "Correct Answers"]]
97
+
98
+ return data
99
+
100
+
101
+ def make_anki(df: pd.DataFrame, out: str, title: str) -> None:
102
+ """
103
+ Creates an Anki deck from the given Kahoot questions
104
+
105
+ :param df: The kahoot questions in a pd.DataFrame
106
+ :param out: The path to the output directory
107
+ :param title: The title of the Anki deck
108
+ :return: None
109
+ """
110
+ my_model = genanki.Model(
111
+ 1607392319,
112
+ "Simple Model",
113
+ fields=[
114
+ {"name": "Question"},
115
+ {"name": "Answer"},
116
+ {"name": "selects"},
117
+ ],
118
+ templates=[
119
+ {
120
+ "name": "Card 1",
121
+ "qfmt": "{{Question}}<br><br>{{selects}}",
122
+ "afmt": '{{FrontSide}}<hr id="answer">{{Answer}}',
123
+ },
124
+ ],
125
+ )
126
+
127
+ my_deck = genanki.Deck(2059400110, title)
128
+
129
+ for index, row in df.iterrows():
130
+ my_note = genanki.Note(
131
+ model=my_model,
132
+ fields=[row["Question"], row["Correct Answers"], row["Possible Answers"]],
133
+ )
134
+ my_deck.add_note(my_note)
135
+
136
+ try:
137
+ genanki.Package(my_deck).write_to_file(
138
+ os.path.join(out, "anki.apkg"),
139
+ )
140
+ except Exception as e:
141
+ logging.error("Failed to write Anki package file: %s", str(e))
@@ -0,0 +1,78 @@
1
+ Metadata-Version: 2.4
2
+ Name: kahoot-to-anki
3
+ Version: 1.1.0
4
+ Summary: CLI tool to convert Kahoot quiz reports into Anki flashcards
5
+ Author: Simon Hardmeier
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: genanki
11
+ Requires-Dist: pandas
12
+ Requires-Dist: openpyxl
13
+ Dynamic: license-file
14
+
15
+ # kahoot-to-anki
16
+ [![Python](https://img.shields.io/badge/python-3.9+-blue.svg)](#installation)
17
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
18
+
19
+ <br>
20
+
21
+ **kahoot-to-anki** is a command‑line tool that converts exported Kahoot quiz reports (Excel Files) into Anki flashcard decks (.apkg format).<br>
22
+ Designed for educators, students, and any self-learners to easily turn quiz results into effective spaced‑repetition decks.
23
+
24
+ ## Installation & Usage
25
+ ### Option 1: Install via pip
26
+ ```
27
+ pip install kahoot-to-anki
28
+ ```
29
+ Then run:
30
+ ```
31
+ kahoot-to-anki --help
32
+ ```
33
+ Example: Process all Kahoot Exports in the `./exports/` folder and write the flashcard deck and CSV file to `./data/`:
34
+ ```
35
+ kahoot-to-anki --inp "./exports" --out "./data" --csv
36
+ ```
37
+
38
+ ### Option 2: Run with Docker
39
+ ```
40
+ # Clone Repository
41
+ git clone https://github.com/SimonHRD/kahoot-to-anki.git
42
+
43
+ # Move into Repository
44
+ cd kahoot-to-anki
45
+
46
+ # Build docker image with the kahoot-to-anki tag
47
+ docker build -t kahoot-to-anki .
48
+
49
+ # Check help command
50
+ docker run --rm kahoot-to-anki --help
51
+
52
+ # Run with local data
53
+ docker run --rm -v "$(pwd)/data:/app/data" kahoot-to-anki --out "./data" --csv
54
+ ```
55
+
56
+ On PowerShell:
57
+ ```
58
+ docker run --rm -v ${PWD}\data:/app/data kahoot-to-anki --out "./data" --csv
59
+ ```
60
+
61
+ ## CLI Arguments
62
+ You can provide either a single Kahoot Excel file or a directory containing multiple `.xlsx` files as input.<br>
63
+ All valid Excel files in the directory will be processed.
64
+
65
+ | Argument | Description |
66
+ |----------------------|--------------------------------------------------------------------------------|
67
+ | `-i`, `--inp` | Path to the input Excel file or directory (default: `./data`) |
68
+ | `-o`, `--out` | Path to the output directory for the Anki deck (default: `./`) |
69
+ | `--sheet` | The Excel Sheet with the raw Kahoot quiz data (default: `RawReportData Data`) |
70
+ | `--csv`, `--no-csv` | Enable or disable CSV export of the questions (default: disabled) |
71
+ | `-t`, `--title` | Title of the generated Anki deck (default: `"Kahoot"`) |
72
+
73
+
74
+ ## Example
75
+ An example Kahoot export file is available in `data/`. The generated deck will be saved as `anki.apkg` in the specified `--out` directory (default: `./`).
76
+
77
+ ## License
78
+ MIT — see [LICENSE](./LICENSE)
@@ -2,7 +2,9 @@ LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
4
  kahoot_to_anki/__init__.py
5
- kahoot_to_anki/converter.py
5
+ kahoot_to_anki/cli.py
6
+ kahoot_to_anki/main.py
7
+ kahoot_to_anki/processing.py
6
8
  kahoot_to_anki.egg-info/PKG-INFO
7
9
  kahoot_to_anki.egg-info/SOURCES.txt
8
10
  kahoot_to_anki.egg-info/dependency_links.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ kahoot-to-anki = kahoot_to_anki.main:main
@@ -1,3 +1,4 @@
1
+ data
1
2
  dist
2
3
  kahoot_to_anki
3
4
  tests
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "kahoot-to-anki"
7
- version = "1.0.0"
7
+ version = "1.1.0"
8
8
  description = "CLI tool to convert Kahoot quiz reports into Anki flashcards"
9
9
  authors = [{ name = "Simon Hardmeier" }]
10
10
  license = "MIT"
11
11
  readme = "README.md"
12
- requires-python = ">=3.8"
12
+ requires-python = ">=3.9"
13
13
  dependencies = [
14
14
  "genanki",
15
15
  "pandas",
@@ -17,7 +17,7 @@ dependencies = [
17
17
  ]
18
18
 
19
19
  [project.scripts]
20
- kahoot-to-anki = "kahoot_to_anki.converter:main"
20
+ kahoot-to-anki = "kahoot_to_anki.main:main"
21
21
 
22
22
  [tool.setuptools.packages.find]
23
23
  where = ["."]
@@ -1,16 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: kahoot-to-anki
3
- Version: 1.0.0
4
- Summary: CLI tool to convert Kahoot quiz reports into Anki flashcards
5
- Author: Simon Hardmeier
6
- License-Expression: MIT
7
- Requires-Python: >=3.8
8
- Description-Content-Type: text/markdown
9
- License-File: LICENSE
10
- Requires-Dist: genanki
11
- Requires-Dist: pandas
12
- Requires-Dist: openpyxl
13
- Dynamic: license-file
14
-
15
- # kahoot-to-anki
16
- > python cli program to convert Kahoot quiz results to Anki flashcards
@@ -1,2 +0,0 @@
1
- # kahoot-to-anki
2
- > python cli program to convert Kahoot quiz results to Anki flashcards
@@ -1 +0,0 @@
1
- """CLI tool to convert Kahoot quiz reports into Anki flashcards."""
@@ -1,254 +0,0 @@
1
- # Standard library imports
2
- import argparse
3
- import logging
4
- import os
5
- import glob
6
-
7
- # Third-party library imports
8
- import genanki
9
- import pandas as pd
10
-
11
- # Configure logging settings
12
- logging.basicConfig(level=logging.INFO)
13
-
14
- # Constants
15
- DEFAULT_INPUT_DIRECTORY = "./data"
16
- DEFAULT_OUTPUT_DIRECTORY = "./"
17
- DEFAULT_DECK_TITLE = "Kahoot"
18
- KAHOOT_EXCEL_SHEET_NAME_RAW_DATA = "RawReportData Data"
19
-
20
-
21
- def main():
22
- # Check command line arguments
23
- inp, out, csv, title = get_commandline_arguments()
24
-
25
- validation(inp, out)
26
-
27
- df = get_questions(inp)
28
-
29
- if csv:
30
- df.to_csv(
31
- os.path.join(out, "kahoot.csv"),
32
- sep=";",
33
- index=False,
34
- encoding="utf-8-sig",
35
- )
36
-
37
- make_anki(df, out, title)
38
-
39
-
40
- def get_commandline_arguments() -> tuple:
41
- """
42
- Parses the command line arguments and returns a tuple with the input path, output path, CSV option, and deck title.
43
-
44
- :return: A tuple with the input path, the output path, the csv and the title of the anki deck
45
- :rtype: tuple
46
- """
47
- parser = argparse.ArgumentParser(description="Create Anki Deck from Kahoot answer")
48
- parser.add_argument(
49
- "-i",
50
- "--inp",
51
- default=DEFAULT_INPUT_DIRECTORY,
52
- help=f"Path to the directory containing input Excel files or a single input Excel file. If a directory is "
53
- f"provided, all Excel files in the directory will be processed. Default: {DEFAULT_INPUT_DIRECTORY}",
54
- type=str,
55
- )
56
- parser.add_argument(
57
- "-o",
58
- "--out",
59
- default=DEFAULT_OUTPUT_DIRECTORY,
60
- help="Path to the directory where the Anki flashcards package will be generated. "
61
- "If not specified, the package will be created in the current working directory.",
62
- type=str,
63
- )
64
- parser.add_argument(
65
- "--csv",
66
- action="store_true",
67
- help="Generate a CSV file with the question data.",
68
- )
69
- parser.add_argument(
70
- "-t",
71
- "--title",
72
- default=DEFAULT_DECK_TITLE,
73
- help="Name of the Anki deck to be created. "
74
- f"If not specified, the default deck name '{DEFAULT_DECK_TITLE}' will be used.",
75
- type=str,
76
- )
77
- args = parser.parse_args()
78
-
79
- # return absolute paths
80
- return os.path.abspath(args.inp), os.path.abspath(args.out), args.csv, args.title
81
-
82
-
83
- def validation(input_directory: str, output_directory: str) -> None:
84
- """
85
- This function validates the command line arguments, checking if the input path is a valid Excel file or directory
86
- and if the output path is a valid directory.
87
- The input path needs to be an Excel file or a directory that contains Excel files.
88
- The output path needs to be a directory and not a file.
89
-
90
- :param input_directory: The path of the input Excel or directory
91
- :param output_directory: The path of the output directory
92
- :return: None
93
- :rtype: None
94
- """
95
- # Check if input is a file
96
- if not os.path.exists(input_directory):
97
- logging.error(f"Input directory {input_directory} does not exist!")
98
- raise FileNotFoundError(f"Input directory {input_directory} does not exist!")
99
- elif (
100
- os.path.isfile(input_directory)
101
- and os.path.splitext(input_directory)[-1] != ".xlsx"
102
- ):
103
- logging.error("Input file is not an excel file!")
104
- raise ValueError("Input file is not an excel file!")
105
- elif os.path.isdir(input_directory):
106
- input_excels = os.path.join(input_directory, "*.xlsx")
107
- if not glob.glob(input_excels):
108
- logging.error("Input directory does not contain any excel files!")
109
- raise FileNotFoundError("Input directory does not contain any excel files!")
110
-
111
- # Check output directory and create when not existing
112
- if not os.path.isdir(output_directory):
113
- logging.error("Output is not a directory!")
114
- raise ValueError("Output is not a directory!")
115
- if not os.path.exists(output_directory):
116
- try:
117
- os.makedirs(output_directory)
118
- except OSError as e:
119
- logging.error(
120
- "Failed to create output directory '%s': %s", output_directory, str(e)
121
- )
122
- raise
123
-
124
-
125
- def get_questions(input_directory: str) -> pd.DataFrame:
126
- """
127
- Extracts all the kahoot questions out of the Excel file(s)
128
-
129
- :param input_directory: The path to the input directory or Excel file
130
- :return: All the questions with the possible answers and the solution
131
- :rtype: pd.DataFrame
132
- """
133
-
134
- def get_excels(path):
135
- """
136
- Returns a list with all Excels in the given path
137
- :param path: the path to an Excel file or a directory with Excel files
138
- :return: a list with all excels
139
- """
140
- if os.path.isfile(path):
141
- yield path
142
- else:
143
- yield from glob.glob(os.path.join(input_directory, "*.xlsx"))
144
- return [f for f in glob.glob(os.path.join(path, "*.xlsx"))]
145
-
146
- def get_excel_data(excel_file: str) -> pd.DataFrame:
147
- """
148
- Returns a pd.DataFrame with the kahoot raw data
149
- :param excel_file: an Excel file with Kahoot raw data
150
- :return: a DataFrame with the data
151
- """
152
- try:
153
- # read file
154
- return pd.read_excel(
155
- excel_file, sheet_name=KAHOOT_EXCEL_SHEET_NAME_RAW_DATA
156
- )
157
- except ValueError:
158
- logging.warning(
159
- "Skipping file '%s' as it is not a valid Excel file.", excel_file
160
- )
161
- return None
162
- except Exception as e:
163
- logging.error("Failed to read file '%s': %s", excel_file, str(e))
164
- return None
165
-
166
- def df_processing(data: pd.DataFrame) -> pd.DataFrame:
167
- """
168
- Processes the Kahoot question data.
169
- :param data: DataFrame with Kahoot question data
170
- :return: Processed DataFrame
171
- """
172
- # delete duplicated questions
173
- data = data.drop_duplicates(subset=["Question Number"])
174
-
175
- data = data.fillna("")
176
-
177
- data["Possible Answers"] = data[
178
- ["Answer 1", "Answer 2", "Answer 3", "Answer 4", "Answer 5", "Answer 6"]
179
- ].agg("<br>".join, axis=1)
180
-
181
- # keep only needed columns
182
- data = data[["Question", "Possible Answers", "Correct Answers"]]
183
-
184
- return data
185
-
186
- out = pd.DataFrame(columns=["Question", "Possible Answers", "Correct Answers"])
187
-
188
- questions_cnt = 0
189
- files_cnt = 0
190
-
191
- for file in get_excels(input_directory):
192
- df = get_excel_data(file)
193
- if df is None:
194
- continue
195
- files_cnt += 1
196
-
197
- df = df_processing(df)
198
-
199
- # add to out dataframe
200
- out = pd.concat([out, df], axis=0, ignore_index=True)
201
-
202
- questions_cnt += len(df)
203
-
204
- logging.info("Read input files: %d", files_cnt)
205
- logging.info("Read questions: %d", questions_cnt)
206
- out = out.drop_duplicates(subset=["Question"])
207
- return out
208
-
209
-
210
- def make_anki(df: pd.DataFrame, out: str, title: str) -> None:
211
- """
212
- Creates an Anki deck from the given Kahoot questions
213
-
214
- :param df: The kahoot questions in a pd.DataFrame
215
- :param out: The path to the output directory
216
- :param title: The title of the Anki deck
217
- :return: None
218
- """
219
- my_model = genanki.Model(
220
- 1607392319,
221
- "Simple Model",
222
- fields=[
223
- {"name": "Question"},
224
- {"name": "Answer"},
225
- {"name": "selects"},
226
- ],
227
- templates=[
228
- {
229
- "name": "Card 1",
230
- "qfmt": "{{Question}}<br><br>{{selects}}",
231
- "afmt": '{{FrontSide}}<hr id="answer">{{Answer}}',
232
- },
233
- ],
234
- )
235
-
236
- my_deck = genanki.Deck(2059400110, title)
237
-
238
- for index, row in df.iterrows():
239
- my_note = genanki.Note(
240
- model=my_model,
241
- fields=[row["Question"], row["Correct Answers"], row["Possible Answers"]],
242
- )
243
- my_deck.add_note(my_note)
244
-
245
- try:
246
- genanki.Package(my_deck).write_to_file(
247
- os.path.join(out, "anki.apkg"),
248
- )
249
- except Exception as e:
250
- logging.error("Failed to write Anki package file: %s", str(e))
251
-
252
-
253
- if __name__ == "__main__":
254
- main()
@@ -1,16 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: kahoot-to-anki
3
- Version: 1.0.0
4
- Summary: CLI tool to convert Kahoot quiz reports into Anki flashcards
5
- Author: Simon Hardmeier
6
- License-Expression: MIT
7
- Requires-Python: >=3.8
8
- Description-Content-Type: text/markdown
9
- License-File: LICENSE
10
- Requires-Dist: genanki
11
- Requires-Dist: pandas
12
- Requires-Dist: openpyxl
13
- Dynamic: license-file
14
-
15
- # kahoot-to-anki
16
- > python cli program to convert Kahoot quiz results to Anki flashcards
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- kahoot-to-anki = kahoot_to_anki.converter:main
File without changes
File without changes