ovos-skill-randomness 0.0.3a1__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,70 @@
1
+ Metadata-Version: 2.1
2
+ Name: ovos-skill-randomness
3
+ Version: 0.0.3a1
4
+ Summary: UNKNOWN
5
+ Home-page: https://github.com/openvoiceos/skill-ovos-randomness
6
+ Author: OpenVoiceOS
7
+ Author-email: mike@oscillatelabs.net
8
+ License: MIT
9
+ Description: # skill-randomness
10
+
11
+ ![Python](https://img.shields.io/badge/python-3.9-blue.svg)
12
+ ![Python](https://img.shields.io/badge/python-3.10-blue.svg)
13
+ ![Python](https://img.shields.io/badge/python-3.11-blue.svg)
14
+
15
+ **Does not support Python 3.8 or lower, please use Python 3.9-3.11**
16
+
17
+ ## About
18
+
19
+ A skill for all kinds of chance - make a choice, roll a die, flip a coin, pick between two choices, etc.
20
+
21
+ Accepts a single property: `die_limit`, which is the maximum number of dice that can be rolled at once. The default is 16.
22
+
23
+ `~/.config/mycroft/skills/skill-randomness.openvoiceos/settings.json`
24
+
25
+ ```json
26
+ {
27
+ "die_limit": 16
28
+ }
29
+ ```
30
+
31
+ ## Examples
32
+
33
+ - "Flip a coin"
34
+ - "Tell me my future"
35
+ - "Help me decide something"
36
+ - "Pick a number between 1 and 100"
37
+ - "Roll a die"
38
+ - "Roll 1 d 20"
39
+ - "Roll 6 d 8"
40
+ - "Roll a 20 sided die"
41
+ - "Roll 5 dice"
42
+ - "Roll 6, 8 sided dice"
43
+
44
+ ## Credits
45
+
46
+ - Mike Gray (@mikejgray)
47
+ - BuilderJer (@builderjer)
48
+
49
+ ## Category
50
+
51
+ Games
52
+ Fun
53
+ Chance
54
+
55
+ ## Tags
56
+
57
+ ovos skill games fun chance
58
+
59
+ ## Attribution
60
+
61
+ The coin flipping sound came from [TheKnave at freesound.org](https://freesound.org/people/TheKnave/sounds/435621/). It is licensed under the [Creative Commons 4 License](https://creativecommons.org/licenses/by-nc/4.0/).
62
+
63
+ The fortune teller sound came from [LittleRainySeasons at freesound.org](https://freesound.org/people/LittleRainySeasons/sounds/335354/). It is licensed under the [Creative Commons 0 License](https://creativecommons.org/publicdomain/zero/1.0/).
64
+
65
+ The dice rolling sound came from [dermotte at freesound.org](https://freesound.org/people/dermotte/sounds/220741/). It is licensed under the [Creative Commons 4 License](https://creativecommons.org/licenses/by/4.0/).
66
+
67
+ Keywords: ovos skill voice assistant
68
+ Platform: UNKNOWN
69
+ Description-Content-Type: text/markdown
70
+ Provides-Extra: test
@@ -0,0 +1,57 @@
1
+ # skill-randomness
2
+
3
+ ![Python](https://img.shields.io/badge/python-3.9-blue.svg)
4
+ ![Python](https://img.shields.io/badge/python-3.10-blue.svg)
5
+ ![Python](https://img.shields.io/badge/python-3.11-blue.svg)
6
+
7
+ **Does not support Python 3.8 or lower, please use Python 3.9-3.11**
8
+
9
+ ## About
10
+
11
+ A skill for all kinds of chance - make a choice, roll a die, flip a coin, pick between two choices, etc.
12
+
13
+ Accepts a single property: `die_limit`, which is the maximum number of dice that can be rolled at once. The default is 16.
14
+
15
+ `~/.config/mycroft/skills/skill-randomness.openvoiceos/settings.json`
16
+
17
+ ```json
18
+ {
19
+ "die_limit": 16
20
+ }
21
+ ```
22
+
23
+ ## Examples
24
+
25
+ - "Flip a coin"
26
+ - "Tell me my future"
27
+ - "Help me decide something"
28
+ - "Pick a number between 1 and 100"
29
+ - "Roll a die"
30
+ - "Roll 1 d 20"
31
+ - "Roll 6 d 8"
32
+ - "Roll a 20 sided die"
33
+ - "Roll 5 dice"
34
+ - "Roll 6, 8 sided dice"
35
+
36
+ ## Credits
37
+
38
+ - Mike Gray (@mikejgray)
39
+ - BuilderJer (@builderjer)
40
+
41
+ ## Category
42
+
43
+ Games
44
+ Fun
45
+ Chance
46
+
47
+ ## Tags
48
+
49
+ ovos skill games fun chance
50
+
51
+ ## Attribution
52
+
53
+ The coin flipping sound came from [TheKnave at freesound.org](https://freesound.org/people/TheKnave/sounds/435621/). It is licensed under the [Creative Commons 4 License](https://creativecommons.org/licenses/by-nc/4.0/).
54
+
55
+ The fortune teller sound came from [LittleRainySeasons at freesound.org](https://freesound.org/people/LittleRainySeasons/sounds/335354/). It is licensed under the [Creative Commons 0 License](https://creativecommons.org/publicdomain/zero/1.0/).
56
+
57
+ The dice rolling sound came from [dermotte at freesound.org](https://freesound.org/people/dermotte/sounds/220741/). It is licensed under the [Creative Commons 4 License](https://creativecommons.org/licenses/by/4.0/).
@@ -0,0 +1,70 @@
1
+ Metadata-Version: 2.1
2
+ Name: ovos-skill-randomness
3
+ Version: 0.0.3a1
4
+ Summary: UNKNOWN
5
+ Home-page: https://github.com/openvoiceos/skill-ovos-randomness
6
+ Author: OpenVoiceOS
7
+ Author-email: mike@oscillatelabs.net
8
+ License: MIT
9
+ Description: # skill-randomness
10
+
11
+ ![Python](https://img.shields.io/badge/python-3.9-blue.svg)
12
+ ![Python](https://img.shields.io/badge/python-3.10-blue.svg)
13
+ ![Python](https://img.shields.io/badge/python-3.11-blue.svg)
14
+
15
+ **Does not support Python 3.8 or lower, please use Python 3.9-3.11**
16
+
17
+ ## About
18
+
19
+ A skill for all kinds of chance - make a choice, roll a die, flip a coin, pick between two choices, etc.
20
+
21
+ Accepts a single property: `die_limit`, which is the maximum number of dice that can be rolled at once. The default is 16.
22
+
23
+ `~/.config/mycroft/skills/skill-randomness.openvoiceos/settings.json`
24
+
25
+ ```json
26
+ {
27
+ "die_limit": 16
28
+ }
29
+ ```
30
+
31
+ ## Examples
32
+
33
+ - "Flip a coin"
34
+ - "Tell me my future"
35
+ - "Help me decide something"
36
+ - "Pick a number between 1 and 100"
37
+ - "Roll a die"
38
+ - "Roll 1 d 20"
39
+ - "Roll 6 d 8"
40
+ - "Roll a 20 sided die"
41
+ - "Roll 5 dice"
42
+ - "Roll 6, 8 sided dice"
43
+
44
+ ## Credits
45
+
46
+ - Mike Gray (@mikejgray)
47
+ - BuilderJer (@builderjer)
48
+
49
+ ## Category
50
+
51
+ Games
52
+ Fun
53
+ Chance
54
+
55
+ ## Tags
56
+
57
+ ovos skill games fun chance
58
+
59
+ ## Attribution
60
+
61
+ The coin flipping sound came from [TheKnave at freesound.org](https://freesound.org/people/TheKnave/sounds/435621/). It is licensed under the [Creative Commons 4 License](https://creativecommons.org/licenses/by-nc/4.0/).
62
+
63
+ The fortune teller sound came from [LittleRainySeasons at freesound.org](https://freesound.org/people/LittleRainySeasons/sounds/335354/). It is licensed under the [Creative Commons 0 License](https://creativecommons.org/publicdomain/zero/1.0/).
64
+
65
+ The dice rolling sound came from [dermotte at freesound.org](https://freesound.org/people/dermotte/sounds/220741/). It is licensed under the [Creative Commons 4 License](https://creativecommons.org/licenses/by/4.0/).
66
+
67
+ Keywords: ovos skill voice assistant
68
+ Platform: UNKNOWN
69
+ Description-Content-Type: text/markdown
70
+ Provides-Extra: test
@@ -0,0 +1,11 @@
1
+ README.md
2
+ setup.py
3
+ ovos_skill_randomness.egg-info/PKG-INFO
4
+ ovos_skill_randomness.egg-info/SOURCES.txt
5
+ ovos_skill_randomness.egg-info/dependency_links.txt
6
+ ovos_skill_randomness.egg-info/entry_points.txt
7
+ ovos_skill_randomness.egg-info/requires.txt
8
+ ovos_skill_randomness.egg-info/top_level.txt
9
+ skill_randomness/__init__.py
10
+ skill_randomness/version.py
11
+ test/test_skill.py
@@ -0,0 +1,3 @@
1
+ [ovos.plugin.skill]
2
+ skill-ovos-randomness.openvoiceos=skill_ovos_randomness:RandomnessSkill
3
+
@@ -0,0 +1,9 @@
1
+ ovos-utils
2
+ ovos-workshop
3
+ ovos-lingua_franca
4
+ icepool
5
+
6
+ [test]
7
+ pytest
8
+ ovos-plugin-manager
9
+ padacioso
@@ -0,0 +1 @@
1
+ skill_ovos_randomness
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env python3
2
+ from setuptools import setup
3
+ from os import walk, path
4
+
5
+ BASEDIR = path.abspath(path.dirname(__file__))
6
+ URL = "https://github.com/openvoiceos/skill-ovos-randomness"
7
+ SKILL_CLAZZ = "RandomnessSkill" # needs to match __init__.py class name
8
+ PYPI_NAME = "ovos-skill-randomness" # pip install PYPI_NAME
9
+
10
+ # below derived from github url to ensure standard skill_id
11
+ SKILL_AUTHOR, SKILL_NAME = URL.split(".com/")[-1].split("/")
12
+ SKILL_PKG = SKILL_NAME.lower().replace("-", "_")
13
+ PLUGIN_ENTRY_POINT = f"{SKILL_NAME.lower()}.{SKILL_AUTHOR.lower()}={SKILL_PKG}:{SKILL_CLAZZ}"
14
+ # skill_id=package_name:SkillClass
15
+ BASE_PATH = BASE_PATH = path.abspath(path.join(path.dirname(__file__), "skill_randomness"))
16
+
17
+
18
+ def get_version():
19
+ """Find the version of the package"""
20
+ version = None
21
+ version_file = path.join(BASE_PATH, "version.py")
22
+ major, minor, build, alpha = (None, None, None, None)
23
+ with open(version_file) as f:
24
+ for line in f:
25
+ if "VERSION_MAJOR" in line:
26
+ major = line.split("=")[1].strip()
27
+ elif "VERSION_MINOR" in line:
28
+ minor = line.split("=")[1].strip()
29
+ elif "VERSION_BUILD" in line:
30
+ build = line.split("=")[1].strip()
31
+ elif "VERSION_ALPHA" in line:
32
+ alpha = line.split("=")[1].strip()
33
+
34
+ if (major and minor and build and alpha) or "# END_VERSION_BLOCK" in line:
35
+ break
36
+ version = f"{major}.{minor}.{build}"
37
+ if alpha and int(alpha) > 0:
38
+ version += f"a{alpha}"
39
+ return version
40
+
41
+
42
+ def get_requirements(requirements_filename: str):
43
+ requirements_file = path.join(path.dirname(__file__), requirements_filename)
44
+ with open(requirements_file, "r", encoding="utf-8") as r:
45
+ requirements = r.readlines()
46
+ requirements = [r.strip() for r in requirements if r.strip() and not r.strip().startswith("#")]
47
+ return requirements
48
+
49
+
50
+ def find_resource_files():
51
+ resource_base_dirs = ("locale", "intents", "dialog", "vocab", "regex", "ui")
52
+ package_data = ["*.json", "*.wav", "*.mp3"]
53
+ for res in resource_base_dirs:
54
+ if path.isdir(path.join(BASE_PATH, res)):
55
+ for directory, _, files in walk(path.join(BASE_PATH, res)):
56
+ if files:
57
+ package_data.append(path.join(directory.replace(BASE_PATH, "").lstrip("/"), "*"))
58
+ return package_data
59
+
60
+
61
+ with open(path.join(path.abspath(path.dirname(__file__)), "README.md"), "r") as f:
62
+ long_description = f.read()
63
+
64
+ setup(
65
+ name=PYPI_NAME,
66
+ version=get_version(),
67
+ description="",
68
+ long_description=long_description,
69
+ long_description_content_type="text/markdown",
70
+ url=URL,
71
+ author="OpenVoiceOS",
72
+ author_email="mike@oscillatelabs.net",
73
+ license="MIT",
74
+ package_dir={SKILL_PKG: "skill_randomness"},
75
+ package_data={SKILL_PKG: find_resource_files()},
76
+ packages=[SKILL_PKG],
77
+ include_package_data=True,
78
+ install_requires=get_requirements("requirements.txt"),
79
+ keywords="ovos skill voice assistant",
80
+ entry_points={"ovos.plugin.skill": PLUGIN_ENTRY_POINT},
81
+ extras_require={"test": get_requirements("requirements-dev.txt")},
82
+ )
@@ -0,0 +1,107 @@
1
+ """A skill for all kinds of chance - make a choice, roll a die, flip a coin, etc."""
2
+ from os.path import dirname
3
+ from random import randint
4
+ from typing import List
5
+
6
+ from icepool import Die, d
7
+
8
+ from ovos_bus_client.message import Message
9
+ from ovos_workshop.decorators import intent_handler
10
+ from lingua_franca.parse import extract_number
11
+ from ovos_workshop.skills import OVOSSkill
12
+
13
+ class RandomnessSkill(OVOSSkill):
14
+ """A skill for all kinds of chance - make a choice, roll a die, flip a coin, etc."""
15
+
16
+ @property
17
+ def die_limit(self):
18
+ return self.settings.get("die_limit", 16)
19
+
20
+ @intent_handler("make-a-choice.intent")
21
+ def handle_make_a_choice_intent(self, message: Message): # pylint: disable=unused-argument
22
+ """Decide between two things."""
23
+ first_choice = self.get_response("first-choice") or "the first one"
24
+ second_choice = self.get_response("second-choice") or "the second one"
25
+ try:
26
+ result = Die([first_choice, second_choice]).sample()
27
+ except TypeError:
28
+ result = Die(first_choice, second_choice).sample()
29
+ self.speak_dialog("choice-result", data={"choice": result})
30
+ self.gui.show_text(result)
31
+ self.enclosure.eyes_blink("b")
32
+ self.enclosure.mouth_text(result)
33
+
34
+ @intent_handler("pick-a-number.intent")
35
+ def handle_pick_a_number(self, message: Message):
36
+ """Pick a number between two numbers."""
37
+ lower_bound = message.data.get("lower", "")
38
+ upper_bound = message.data.get("upper", "")
39
+ self.log.debug(f"Lower: {lower_bound}, Upper: {upper_bound}")
40
+ try:
41
+ upper_bound = round(float(upper_bound))
42
+ lower_bound = round(float(lower_bound))
43
+ except ValueError:
44
+ lower_bound = 1
45
+ upper_bound = 10
46
+ self.speak_dialog("number-range-not-specified")
47
+ result = randint(lower_bound, upper_bound)
48
+ self.speak_dialog("number-result", data={"number": result})
49
+ self.gui.show_text(str(result))
50
+ self.enclosure.eyes_spin()
51
+ self.enclosure.mouth_text(str(result))
52
+
53
+ @intent_handler("flip-a-coin.intent")
54
+ def handle_flip_a_coin(self, message: Message): # pylint: disable=unused-argument
55
+ """Flip a coin."""
56
+ self.play_audio(f"{dirname(__file__)}/coin-flip.wav")
57
+ try:
58
+ result = Die(["heads", "tails"]).sample()
59
+ except TypeError:
60
+ result = Die("heads", "tails").sample()
61
+ self.speak_dialog("coin-result", data={"result": result})
62
+ self.gui.show_text(result)
63
+ self.enclosure.system_blink(3)
64
+ self.enclosure.mouth_text(result)
65
+
66
+ @intent_handler("fortune-teller.intent")
67
+ def handle_fortune_teller(self, message: Message): # pylint: disable=unused-argument
68
+ """Get a random fortune."""
69
+ self.play_audio(f"{dirname(__file__)}/magic.mp3")
70
+ fortune = self.get_response("fortune-query")
71
+ try:
72
+ answer = Die(["yes", "no"]).sample()
73
+ except TypeError:
74
+ answer = Die("yes", "no").sample()
75
+ self.speak_dialog("fortune-result", {"answer": answer})
76
+ fortune_with_answer = f"{fortune}? ...{answer}"
77
+ self.gui.show_text(fortune_with_answer)
78
+ self.enclosure.eyes_spin()
79
+ self.enclosure.mouth_text(fortune_with_answer)
80
+
81
+ @intent_handler("roll-single-die.intent")
82
+ def handle_roll_single_die(self, message: Message):
83
+ """Roll a single die."""
84
+ faces = extract_number(message.data.get("faces", "6"))
85
+ self.play_audio(f"{dirname(__file__)}/die-roll.wav")
86
+ self.log.debug(f"Rolling a die with {faces} faces")
87
+ result = Die(d(int(faces))).sample()
88
+ self.speak_dialog("die-result", data={"result": result})
89
+ self.gui.show_text(str(result))
90
+ self.enclosure.eyes_spin()
91
+ self.enclosure.mouth_text(str(result))
92
+
93
+ @intent_handler("roll-multiple-dice.intent")
94
+ def handle_roll_multiple_dice(self, message: Message):
95
+ """Roll multiple dice."""
96
+ number = extract_number(message.data.get("number"))
97
+ faces = extract_number(message.data.get("faces", "6"))
98
+ self.play_audio(f"{dirname(__file__)}/die-roll.wav")
99
+ if number > self.die_limit:
100
+ self.speak_dialog("over-dice-limit", data={"number": self.die_limit})
101
+ number = self.die_limit
102
+ self.log.debug(f"Rolling {number} dice with {faces} faces")
103
+ result_list: List[int] = []
104
+ for _ in range(1, int(number) + 1):
105
+ val = Die(d(int(faces))).sample()
106
+ result_list.append(val)
107
+ self.speak_dialog("multiple-die-result", data={"result_string": ", ".join([str(x) for x in result_list]), "result_total": str(sum(result_list))})
@@ -0,0 +1,9 @@
1
+ # START_VERSION_BLOCK
2
+ VERSION_MAJOR = 0
3
+ VERSION_MINOR = 0
4
+ VERSION_BUILD = 3
5
+ VERSION_ALPHA = 1
6
+ # END_VERSION_BLOCKVERSION_MAJOR = 0
7
+ VERSION_MINOR = 0
8
+ VERSION_BUILD = 1
9
+ VERSION_ALPHA = 0
@@ -0,0 +1,61 @@
1
+ # pylint: disable=missing-docstring
2
+ import shutil
3
+ from json import dumps
4
+ from os import environ, getenv, makedirs
5
+ from os.path import join, dirname, isdir
6
+ from unittest.mock import Mock
7
+ import pytest
8
+ from ovos_plugin_manager.skills import find_skill_plugins
9
+ from ovos_utils.fakebus import FakeBus
10
+
11
+ from skill_randomness import RandomnessSkill
12
+
13
+
14
+ @pytest.fixture(scope="session")
15
+ def test_skill(test_skill_id="skill-ovos-randomness.openvoiceos", bus=FakeBus()):
16
+ # Get test skill
17
+ bus.emitter = bus.ee
18
+ bus.run_forever()
19
+ skill_entrypoint = getenv("TEST_SKILL_ENTRYPOINT")
20
+ if not skill_entrypoint:
21
+ skill_entrypoints = list(find_skill_plugins().keys())
22
+ assert test_skill_id in skill_entrypoints
23
+ skill_entrypoint = test_skill_id
24
+
25
+ skill = RandomnessSkill(skill_id=test_skill_id, bus=bus)
26
+ skill.speak = Mock()
27
+ skill.speak_dialog = Mock()
28
+ skill.play_audio = Mock()
29
+ yield skill
30
+ shutil.rmtree(join(dirname(__file__), "skill_fs"), ignore_errors=False)
31
+
32
+
33
+ @pytest.fixture(scope="function")
34
+ def reset_skill_mocks(test_skill):
35
+ # Reset mocks before each test
36
+ test_skill.speak.reset_mock()
37
+ test_skill.speak_dialog.reset_mock()
38
+ test_skill.play_audio.reset_mock()
39
+
40
+
41
+ class TestRandomnessSkill:
42
+ test_fs = join(dirname(__file__), "skill_fs")
43
+ data_dir = join(test_fs, "data")
44
+ conf_dir = join(test_fs, "config")
45
+ environ["XDG_DATA_HOME"] = data_dir
46
+ environ["XDG_CONFIG_HOME"] = conf_dir
47
+ if not isdir(test_fs):
48
+ makedirs(data_dir)
49
+ makedirs(conf_dir)
50
+
51
+ with open(join(conf_dir, "mycroft.conf"), "w", encoding="utf-8") as f:
52
+ f.write(dumps({"Audio": {"backends": {"ocp": {"active": False}}}}))
53
+
54
+ def test_nada(self, test_skill):
55
+ assert True
56
+
57
+ def test_skill_is_a_valid_plugin():
58
+ assert "skill-ovos-randomness.openvoiceos" in find_skill_plugins()
59
+
60
+ if __name__ == "__main__":
61
+ pytest.main()