diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b3040cb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,163 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+*.ipynb
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+Pipfile.lock
+Pipfile
+
+# poetry
+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+# in version control.
+# https://pdm.fming.dev/#use-with-ide
+.pdm.toml
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+# and can be added to the global gitignore or merged into this file. For a more nuclear
+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
+#.idea/
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..0542b31
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 Ingenjörsarbete För Klimatet
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index 9f7fc00..29a2d3e 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,48 @@
-# co2-meal-planner
-co2-meal-planner
+
ifk-co2-meal-planner
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Description
+
+Welcome to ifk-co2-meal-planner.
+
+## Configuration
+
+When you start a new project, apart from the obvious changes,
+there are some details to consider.
+
+- Build workflow, follow the guide in [dynamic badges](https://github.com/Schneegans/dynamic-badges-action).
+- To build docs, change `branch` in `github/workflows/github-action-docs.yaml`
+from `["SET_TO_MAIN"]` to `["main"]`. You also need to activate Pages under repo
+Settings/Pages.
diff --git a/docs/assets/favicon.png b/docs/assets/favicon.png
new file mode 100644
index 0000000..44ea633
Binary files /dev/null and b/docs/assets/favicon.png differ
diff --git a/docs/assets/ifk_logo_black.png b/docs/assets/ifk_logo_black.png
new file mode 100644
index 0000000..6f81d61
Binary files /dev/null and b/docs/assets/ifk_logo_black.png differ
diff --git a/docs/assets/ifk_logo_white.png b/docs/assets/ifk_logo_white.png
new file mode 100644
index 0000000..5a0816b
Binary files /dev/null and b/docs/assets/ifk_logo_white.png differ
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..ecdd4a7
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,3 @@
+# Welcome to ifk-co2-meal-planner
+
+Docs for ifk-co2-meal-planner.
diff --git a/material/partials/copyright.html b/material/partials/copyright.html
new file mode 100644
index 0000000..d05edfe
--- /dev/null
+++ b/material/partials/copyright.html
@@ -0,0 +1,14 @@
+{#-
+This file was automatically generated - do not edit
+-#}
+
diff --git a/mkdocs.yml b/mkdocs.yml
new file mode 100644
index 0000000..5552478
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,37 @@
+site_name: ifk-co2-meal-planner
+repo_url: https://github.com/Ingenjorsarbete-For-Klimatet/ifk-co2-meal-planner
+site_author: IFK
+site_url: https://ingenjorsarbete-for-klimatet.github.io/ifk-co2-meal-planner/
+repo_name: Ingenjorsarbete-For-Klimatet/ifk-co2-meal-planner
+
+nav:
+- Home: index.md
+
+watch:
+- src
+
+theme:
+ name: material
+ custom_dir: material
+ palette:
+ scheme: default
+ primary: black
+ accent: light green
+ language: en
+ icon:
+ repo: fontawesome/brands/git-alt
+ logo: assets/ifk_logo_white.png
+ favicon: assets/favicon.png
+ features:
+ - navigation.tabs
+
+plugins:
+- search
+- mkdocstrings
+
+markdown_extensions:
+ - pymdownx.highlight:
+ anchor_linenums: true
+ - pymdownx.inlinehilite
+ - pymdownx.snippets
+ - pymdownx.superfences
diff --git a/notebooks/example.py b/notebooks/example.py
new file mode 100644
index 0000000..12050b0
--- /dev/null
+++ b/notebooks/example.py
@@ -0,0 +1,134 @@
+# %%
+"""Example.
+
+https://www.livsmedelsverket.se/om-oss/psidata/livsmedelsdatbasenalfa
+
+ClimateHub have open source on CHG, but only free for internal use.
+"""
+
+import pandas as pd
+
+# from IPython.display import display
+from ifk_co2_meal_planner.rdi import rdi
+from ifk_co2_meal_planner.slv_wrapper import SlvWrapper
+
+slv = SlvWrapper()
+
+
+# %%
+slv.search_food("paranöt")
+
+menu = {
+ "Mango": {"number": 574, "weight": 100},
+ "cashew": {"number": 1557, "weight": 65 / 4},
+ "hirs": {"number": 834, "weight": 1180.0 / 5},
+ "kikärtor": {"number": 3815, "weight": 250 / 4},
+ "basilika": {"number": 379, "weight": 3},
+ "apelsin": {"number": 551, "weight": 80},
+}
+
+slv.get_minerals_from_number(1568)
+
+
+# %%
+
+mineral_dict = slv.populate_mineral_dict(menu)
+mineral_df = slv.mineral_dict_to_df(mineral_dict)
+mineral_df = slv.convert_betakaroten_to_retinol(mineral_df)
+print(mineral_df)
+
+mineral_df = slv.calculate_minerals_for_weight(mineral_df)
+
+print(mineral_df)
+
+# calculate total
+mineral_df.loc["total"] = mineral_df.sum()
+
+# create an own class for rdi?
+rdi_dict = slv.init_mineral_dict()
+for gen in rdi["Zink, Zn"].keys():
+ for col in rdi_dict.keys():
+ if col in rdi.keys():
+ rdi_dict[col].append(rdi[col][gen])
+ elif col == "name":
+ rdi_dict["name"].append(gen)
+ else:
+ rdi_dict[col].append(None)
+
+rdi_df = pd.DataFrame.from_dict(rdi_dict)
+rdi_df.set_index("name", inplace=True)
+mineral_df = pd.concat([mineral_df, rdi_df])
+
+pd.set_option("display.max_columns", 500)
+print(mineral_df)
+
+
+# %%
+
+for gen in rdi["Zink, Zn"].keys():
+ mineral_df.loc[gen + " percentage"] = rdi_per = (
+ mineral_df.loc["total"] / mineral_df.loc[gen] * 100
+ )
+
+# ax = mineral_df['total'].plot.bar(rot=0)
+rdi_per_labels = ["female percentage", "male percentage", "4-6 years percentage"]
+ax = mineral_df.loc[rdi_per_labels].dropna(axis=1, how="all").transpose().plot.barh()
+ax.legend(bbox_to_anchor=(1.42, 1))
+ax.axvline(x=100)
+ax.set_xlim([0, 100])
+ax.grid()
+
+
+# %%
+# get classifications
+a = slv.get_ingredients_from_number(300)
+
+classifications = []
+for i in range(1, 70):
+ classification = slv.get_calssification_from_number(i)
+ try:
+ if len(slv.get_ingredients_from_number(i)) == 1:
+ if classification[-1]["kod"] not in classifications:
+ classifications.append(classification[-1]["kod"])
+ except Exception:
+ print("did not find number: ", i)
+
+for x in classifications:
+ print(x)
+
+# %%
+menu = {
+ "Mango": {"number": 574, "weight": 50},
+ "Cashewnötter rostade u. salt": {"number": 1557, "weight": 20},
+ "Hirs kokt m. salt fullkorn": {"number": 834, "weight": 100},
+ "Potatisgratäng m. lättmjölk ost mager hemlagad": {"number": 279, "weight": 300},
+}
+
+# breakdown to ingredients
+menu_ingredients = {}
+for key, value_dict in menu.items():
+ ingredients = slv.get_ingredients_from_number(value_dict["number"])
+ if len(ingredients) == 1:
+ if key in menu_ingredients.keys():
+ menu_ingredients[key]["weight"] = (
+ menu_ingredients[key]["weight"] + value_dict["weight"]
+ )
+ else:
+ menu_ingredients[key] = value_dict
+ else:
+ total_weight = value_dict["weight"]
+ for food in ingredients:
+ number = slv.get_number_from_name(food["namn"])
+ weight = (total_weight * food["andel"]) / 100
+ if food["namn"] in menu_ingredients.keys():
+ menu_ingredients[food["namn"]]["weight"] = (
+ menu_ingredients[food["namn"]]["weight"] + weight
+ )
+ else:
+ menu_ingredients[food["namn"]] = {"number": number, "weight": weight}
+
+
+# %%
+
+
+a = slv.search_food("Mjölk")
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..ea97c17
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,56 @@
+[build-system]
+requires = ["setuptools", "setuptools-scm"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "ifk-co2-meal-planner"
+version = "0.1.0"
+description = "For evaluation of nutrition and CHG of meals."
+license = { text = "MIT" }
+readme = "README.md"
+authors = [
+ { name = "IFK", email = "info@ingenjorsarbeteforklimatet.se" },
+]
+requires-python = ">=3.9"
+dependencies = ["requests==2.31.0",
+ "pandas==2.2.0",
+ "matplotlib==3.8.2",
+ "pyarrow==15.0.0"
+]
+
+[project.optional-dependencies]
+lint = [
+ "ruff ~= 0.1",
+]
+type = ["mypy ~= 1.7", "types-requests ~= 2.28", "pandas-stubs ~= 1.5"]
+test = ["pytest ~= 7.1", "coverage ~= 6.5", "pytest-cov ~= 4.0"]
+doc = [
+ "mkdocs ~= 1.4",
+ "mkdocs-material ~= 8.5",
+ "mkdocstrings[python] ~= 0.19",
+]
+dev = [
+ "ifk-co2-meal-planner[lint]",
+ "ifk-co2-meal-planner[type]",
+ "ifk-co2-meal-planner[test]",
+ "ifk-co2-meal-planner[doc]",
+ "pre-commit ~= 2.20",
+ "ipykernel ~= 6.26",
+]
+
+[tool.setuptools.packages.find]
+where = ["src"]
+exclude = ["material"]
+
+[tool.ruff]
+line-length = 88
+extend-include = ["*.ipynb"]
+
+[tool.ruff.lint]
+select = ["E4", "E7", "E9", "W", "F", "B", "D", "I", "S"]
+ignore = ["D203", "D213", "S101"]
+unfixable = ["B", "S"]
+pydocstyle.convention = "google"
+
+[tool.mypy]
+ignore_missing_imports = true
diff --git a/src/ifk_co2_meal_planner/rdi.py b/src/ifk_co2_meal_planner/rdi.py
new file mode 100644
index 0000000..fcb3a4a
--- /dev/null
+++ b/src/ifk_co2_meal_planner/rdi.py
@@ -0,0 +1,24 @@
+"""RDI list."""
+
+# Zink ett intag på 25-30% högre rekommenderas vid veg kost
+
+rdi = {
+ "Zink, Zn": {"male": 12.7, "female": 9.7, "4-6 years": 5.8},
+ "Vitamin E": {"male": 11, "female": 10, "4-6 years": 8},
+ "Vitamin D": {"male": 10, "female": 10, "4-6 years": 10},
+ "Vitamin C": {"male": 110, "female": 95, "4-6 years": 35},
+ "Vitamin B6": {"male": 1.8, "female": 1.6, "4-6 years": 0.7},
+ "Vitamin B12": {"male": 4, "female": 4, "4-6 years": 1.7},
+ "Tiamin": {"male": 0.1, "female": 0.1, "4-6 years": 0.1},
+ "Selen, Se": {"male": 90, "female": 75, "4-6 years": 25},
+ "Riboflavin": {"male": 1.6, "female": 1.6, "4-6 years": 0.7},
+ "Retinol": {"male": 800, "female": 700, "4-6 years": 350},
+ "Fosfor, P": {"male": 520, "female": 520, "4-6 years": 440},
+ "Niacinekvivalenter": {"male": 1.6, "female": 1.6, "4-6 years": 1.6},
+ "Magnesium, Mg": {"male": 350, "female": 300, "4-6 years": 230},
+ "Kalium, K": {"male": 3500, "female": 3500, "4-6 years": 1150},
+ "Jod, I": {"male": 150, "female": 150, "4-6 years": 100},
+ "Folat": {"male": 330, "female": 330, "4-6 years": 140},
+ "Järn, Fe": {"male": 9, "female": 15, "4-6 years": 7},
+ "Kalcium, Ca": {"male": 950, "female": 950, "4-6 years": 800},
+}
diff --git a/src/ifk_co2_meal_planner/slv_wrapper.py b/src/ifk_co2_meal_planner/slv_wrapper.py
new file mode 100644
index 0000000..218612a
--- /dev/null
+++ b/src/ifk_co2_meal_planner/slv_wrapper.py
@@ -0,0 +1,160 @@
+""""Request data from livsmedelsverket."""
+
+import pandas as pd
+import requests
+
+
+class SlvWrapper:
+ """Class for fetcing and process slv data."""
+
+ def __init__(self) -> None:
+ """Initialization."""
+ self.version = 1
+ list_of_foods_url = f"https://dataportal.livsmedelsverket.se/livsmedel/api/v{self.version}/livsmedel?offset=0&limit=2556&sprak=1"
+ all_foods = requests.get(list_of_foods_url) # noqa: S113
+ self.all_foods = all_foods.json()["livsmedel"]
+
+ def search_food(self, food: str) -> None:
+ """Search for string in slv.
+
+ Args:
+ food: name of food to search for.
+ """
+ for livsmedel in self.all_foods:
+ if food.lower() in livsmedel["namn"].lower():
+ print(livsmedel["namn"], livsmedel["nummer"])
+
+ pass
+
+ def get_number_from_name(self, food: str) -> int:
+ """Get number from name.
+
+ Args:
+ food: name of food to search for.
+
+ Retruns:
+ number of food.
+ """
+ number = -1
+ for livsmedel in self.all_foods:
+ if food == livsmedel["namn"]:
+ number = livsmedel["nummer"]
+ break
+
+ return number
+
+ def get_minerals_from_number(self, number: int) -> dict:
+ """Get minerals and vitamins for given number.
+
+ Args:
+ number: number corresponding to a specific food
+
+ Returns:
+ dict with mineals etc corresponding to food number
+ """
+ url = f"https://dataportal.livsmedelsverket.se/livsmedel/api/v{self.version}/livsmedel/{number}/naringsvarden"
+ temp_minerals = requests.get(url).json() # noqa: S113
+ return temp_minerals
+
+ def get_ingredients_from_number(self, number: int) -> dict:
+ """Get ingredients for given number.
+
+ Args:
+ number: number corresponding to a specific food
+
+ Returns:
+ dict with ingredients
+ """
+ url = f"https://dataportal.livsmedelsverket.se/livsmedel/api/v{self.version}/livsmedel/{number}/ravaror"
+ ingredients = requests.get(url).json() # noqa: S113
+ return ingredients
+
+ def get_classification_from_number(self, number: int) -> dict:
+ """Get classification from number.
+
+ Args:
+ number: number corresponding to a specific food
+
+ Returns:
+ dict classification
+ """
+ url = f"https://dataportal.livsmedelsverket.se/livsmedel/api/v{self.version}/livsmedel/{number}/klassificeringar"
+ classification_from_number = requests.get(url).json() # noqa: S113
+ return classification_from_number
+
+ def init_mineral_dict(self) -> dict:
+ """Initialization of mineral dict.
+
+ Returns:
+ dict with keys corresponding to minerals etc.
+ """
+ temp = self.get_minerals_from_number(1)
+ mineral_dict: dict = {mineral["namn"]: [] for mineral in temp}
+ mineral_dict["name"] = []
+ mineral_dict["weight"] = []
+ return mineral_dict
+
+ def populate_mineral_dict(self, menu: dict) -> dict:
+ """Populate mineral dict with minearls from set of foods.
+
+ Args:
+ menu: dict with foods on format {name: {number: x, weight: y}}
+
+ Returns:
+ dict with minerals etc (/100g) corresponding to menu
+
+ """
+ mineral_dict = self.init_mineral_dict()
+ for key, item in menu.items():
+ mineral_dict["name"].append(key)
+ mineral_dict["weight"].append(item["weight"])
+ temp_minerals = self.get_minerals_from_number(item["number"])
+ for mineral in temp_minerals:
+ mineral_dict[mineral["namn"]].append(mineral["varde"])
+
+ return mineral_dict
+
+ def mineral_dict_to_df(self, mineral_dict: dict) -> pd.DataFrame:
+ """Convert minearl dict to dataframe.
+
+ Args:
+ mineral_dict: dict with minearals etc.
+
+ Returns:
+ Dataframe with minerals etc.
+ """
+ mineral_df = pd.DataFrame.from_dict(mineral_dict)
+ mineral_df.set_index("name", inplace=True)
+ mineral_df = mineral_df.astype(float)
+ return mineral_df
+
+ def convert_betakaroten_to_retinol(self, mineral_df: pd.DataFrame) -> pd.DataFrame:
+ """Convert betakaroten to retinol.
+
+ Factor according to slv.
+
+ Args:
+ mineral_df: dataframe with minerals etc.
+
+ Returns:
+ Dataframe with Retinol modified.
+ """
+ factor = 12
+ mineral_df["Retinol"] = (
+ mineral_df["Retinol"] + mineral_df["Betakaroten/β-Karoten"] / factor
+ )
+
+ return mineral_df
+
+ def calculate_minerals_for_weight(self, mineral_df: pd.DataFrame) -> pd.DataFrame:
+ """Adjust minerals by weight.
+
+ Args:
+ mineral_df: dataframe with minerals etc
+
+ Returns:
+ dataframe with minerals etc adjusted.
+ """
+ for index, row in mineral_df.iterrows():
+ mineral_df.loc[index] = mineral_df.loc[index] * row["weight"] / 100.0
+ return mineral_df
diff --git a/tests/test_unit.py b/tests/test_unit.py
new file mode 100644
index 0000000..2eca37e
--- /dev/null
+++ b/tests/test_unit.py
@@ -0,0 +1,8 @@
+"""Temporary unit test."""
+
+from co2_meal_planner.slv_wrapper import temp
+
+
+def test_unit_temp():
+ """Unit test of temp function."""
+ assert temp() is True