skill-easter-eggs 0.0.1a1__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.
- skill-easter-eggs-0.0.1a1/LICENSE +28 -0
- skill-easter-eggs-0.0.1a1/PKG-INFO +45 -0
- skill-easter-eggs-0.0.1a1/README.md +31 -0
- skill-easter-eggs-0.0.1a1/__init__.py +167 -0
- skill-easter-eggs-0.0.1a1/setup.cfg +4 -0
- skill-easter-eggs-0.0.1a1/setup.py +89 -0
- skill-easter-eggs-0.0.1a1/skill_easter_eggs.egg-info/PKG-INFO +45 -0
- skill-easter-eggs-0.0.1a1/skill_easter_eggs.egg-info/SOURCES.txt +11 -0
- skill-easter-eggs-0.0.1a1/skill_easter_eggs.egg-info/dependency_links.txt +1 -0
- skill-easter-eggs-0.0.1a1/skill_easter_eggs.egg-info/entry_points.txt +3 -0
- skill-easter-eggs-0.0.1a1/skill_easter_eggs.egg-info/top_level.txt +1 -0
- skill-easter-eggs-0.0.1a1/stardate.py +295 -0
- skill-easter-eggs-0.0.1a1/version.py +1 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023, [fullname]
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: skill-easter-eggs
|
|
3
|
+
Version: 0.0.1a1
|
|
4
|
+
Summary: UNKNOWN
|
|
5
|
+
Home-page: https://github.com/OpenVoiceOS/skill-easter-eggs
|
|
6
|
+
Author: Jarbas
|
|
7
|
+
Author-email: jarbas@openvoiceos.com
|
|
8
|
+
License: BSD-3-Clause
|
|
9
|
+
Platform: UNKNOWN
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
|
|
13
|
+
## Easter Eggs
|
|
14
|
+
|
|
15
|
+
[](https://en.cryptobadges.io/donate/1QJNhKM8tVv62XSUrST2vnaMXh5ADSyYP8)
|
|
16
|
+
[](https://paypal.me/jarbasai)
|
|
17
|
+
<span class="badge-patreon"><a href="https://www.patreon.com/jarbasAI" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span>
|
|
18
|
+
[](https://saythanks.io/to/JarbasAl)
|
|
19
|
+
|
|
20
|
+
pop culture references skill
|
|
21
|
+
|
|
22
|
+
## Description
|
|
23
|
+
|
|
24
|
+
Some funny things for mycroft, mostly quotes from movies
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
- "current stardate"
|
|
29
|
+
- "open the pod bay doors"
|
|
30
|
+
- "first law of robotics"
|
|
31
|
+
- "how to play rock_paper_scissors_lizard_spock"
|
|
32
|
+
- "how many languages do you speak"
|
|
33
|
+
- "do you like portal"
|
|
34
|
+
- "what would duke nukem say"
|
|
35
|
+
- "what would HAL 9000 say"
|
|
36
|
+
- "what would arnold say"
|
|
37
|
+
- "what would glados say"
|
|
38
|
+
- "what would bender say"
|
|
39
|
+
|
|
40
|
+
## Credits
|
|
41
|
+
|
|
42
|
+
JarbasAI
|
|
43
|
+
mikejgray (revival)
|
|
44
|
+
|
|
45
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
## Easter Eggs
|
|
2
|
+
|
|
3
|
+
[](https://en.cryptobadges.io/donate/1QJNhKM8tVv62XSUrST2vnaMXh5ADSyYP8)
|
|
4
|
+
[](https://paypal.me/jarbasai)
|
|
5
|
+
<span class="badge-patreon"><a href="https://www.patreon.com/jarbasAI" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span>
|
|
6
|
+
[](https://saythanks.io/to/JarbasAl)
|
|
7
|
+
|
|
8
|
+
pop culture references skill
|
|
9
|
+
|
|
10
|
+
## Description
|
|
11
|
+
|
|
12
|
+
Some funny things for mycroft, mostly quotes from movies
|
|
13
|
+
|
|
14
|
+
## Examples
|
|
15
|
+
|
|
16
|
+
- "current stardate"
|
|
17
|
+
- "open the pod bay doors"
|
|
18
|
+
- "first law of robotics"
|
|
19
|
+
- "how to play rock_paper_scissors_lizard_spock"
|
|
20
|
+
- "how many languages do you speak"
|
|
21
|
+
- "do you like portal"
|
|
22
|
+
- "what would duke nukem say"
|
|
23
|
+
- "what would HAL 9000 say"
|
|
24
|
+
- "what would arnold say"
|
|
25
|
+
- "what would glados say"
|
|
26
|
+
- "what would bender say"
|
|
27
|
+
|
|
28
|
+
## Credits
|
|
29
|
+
|
|
30
|
+
JarbasAI
|
|
31
|
+
mikejgray (revival)
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# pylint: disable=unused-import,missing-docstring,invalid-name
|
|
2
|
+
# Copyright 2016 Mycroft AI, Inc.
|
|
3
|
+
#
|
|
4
|
+
# This file is part of Mycroft Core.
|
|
5
|
+
#
|
|
6
|
+
# Mycroft Core is free software: you can redistribute it and/or modify
|
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
# (at your option) any later version.
|
|
10
|
+
#
|
|
11
|
+
# Mycroft Core is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU General Public License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You should have received a copy of the GNU General Public License
|
|
17
|
+
# along with Mycroft Core. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
|
|
19
|
+
import random
|
|
20
|
+
from os import listdir
|
|
21
|
+
from os.path import dirname
|
|
22
|
+
|
|
23
|
+
from adapt.intent import IntentBuilder
|
|
24
|
+
from mycroft.skills.audioservice import AudioService
|
|
25
|
+
from ovos_workshop.skills import OVOSSkill
|
|
26
|
+
|
|
27
|
+
from .stardate import Stardate
|
|
28
|
+
|
|
29
|
+
__author__ = "jarbas"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class EasterEggsSkill(OVOSSkill):
|
|
33
|
+
def __init__(self, *args, **kwargs):
|
|
34
|
+
super().__init__(*args, **kwargs)
|
|
35
|
+
|
|
36
|
+
def initialize(self):
|
|
37
|
+
stardate_intent = IntentBuilder("StardateIntent").require("StardateKeyword").build()
|
|
38
|
+
self.register_intent(stardate_intent, self.handle_stardate_intent)
|
|
39
|
+
|
|
40
|
+
intent = IntentBuilder("PodBayDoorsIntent").require("PodBayDoorsKeyword").build()
|
|
41
|
+
self.register_intent(intent, self.handle_pod_intent)
|
|
42
|
+
|
|
43
|
+
intent = IntentBuilder("LanguagesYouSpeakIntent").require("LanguagesYouSpeakKeyword").build()
|
|
44
|
+
self.register_intent(intent, self.handle_number_of_languages_intent)
|
|
45
|
+
|
|
46
|
+
intent = (
|
|
47
|
+
IntentBuilder("RoboticsLawsIntent")
|
|
48
|
+
.require("RoboticsKeyword")
|
|
49
|
+
.require("LawKeyword")
|
|
50
|
+
.optionally("LawOfRobotics")
|
|
51
|
+
.build()
|
|
52
|
+
)
|
|
53
|
+
self.register_intent(intent, self.handle_robotic_laws_intent)
|
|
54
|
+
|
|
55
|
+
intent = (
|
|
56
|
+
IntentBuilder("rock_paper_scissors_lizard_spock_Intent")
|
|
57
|
+
.require("rock_paper_scissors_lizard_spock_Keyword")
|
|
58
|
+
.build()
|
|
59
|
+
)
|
|
60
|
+
self.register_intent(intent, self.handle_rock_paper_scissors_lizard_spock_intent)
|
|
61
|
+
|
|
62
|
+
intent = IntentBuilder("PortalIntent").require("PortalKeyword").build()
|
|
63
|
+
self.register_intent(intent, self.handle_portal_intent)
|
|
64
|
+
|
|
65
|
+
intent = IntentBuilder("DukeNukemIntent").require("DukeNukemKeyword").build()
|
|
66
|
+
self.register_intent(intent, self.handle_dukenukem_intent)
|
|
67
|
+
|
|
68
|
+
intent = IntentBuilder("HALIntent").require("HALKeyword").build()
|
|
69
|
+
self.register_intent(intent, self.handle_hal_intent)
|
|
70
|
+
|
|
71
|
+
intent = IntentBuilder("BenderIntent").require("BenderKeyword").build()
|
|
72
|
+
self.register_intent(intent, self.handle_bender_intent)
|
|
73
|
+
|
|
74
|
+
intent = IntentBuilder("ArnoldIntent").require("ArnoldKeyword").build()
|
|
75
|
+
self.register_intent(intent, self.handle_arnold_intent)
|
|
76
|
+
|
|
77
|
+
intent = IntentBuilder("GladosIntent").require("GladosKeyword").build()
|
|
78
|
+
self.register_intent(intent, self.handle_glados_intent)
|
|
79
|
+
|
|
80
|
+
self.audio_service = AudioService(self.emitter)
|
|
81
|
+
|
|
82
|
+
def handle_stardate_intent(self, _):
|
|
83
|
+
sd = Stardate().toStardate()
|
|
84
|
+
self.speak_dialog("stardate", {"stardate": sd})
|
|
85
|
+
|
|
86
|
+
def handle_pod_intent(self, _):
|
|
87
|
+
self.speak_dialog("pod")
|
|
88
|
+
|
|
89
|
+
def handle_robotic_laws_intent(self, message):
|
|
90
|
+
law = str(message.data.get("LawOfRobotics", "all"))
|
|
91
|
+
if law == "1":
|
|
92
|
+
self.speak_dialog("rule1")
|
|
93
|
+
elif law == "2":
|
|
94
|
+
self.speak_dialog("rule2")
|
|
95
|
+
elif law == "3":
|
|
96
|
+
self.speak_dialog("rule3")
|
|
97
|
+
else:
|
|
98
|
+
self.speak_dialog("rule1")
|
|
99
|
+
self.speak_dialog("rule2")
|
|
100
|
+
self.speak_dialog("rule3")
|
|
101
|
+
|
|
102
|
+
def handle_rock_paper_scissors_lizard_spock_intent(self, _):
|
|
103
|
+
self.speak_dialog("rock_paper_scissors_lizard_spock")
|
|
104
|
+
|
|
105
|
+
def handle_number_of_languages_intent(self, _):
|
|
106
|
+
self.speak_dialog("languages")
|
|
107
|
+
|
|
108
|
+
def handle_portal_intent(self, _):
|
|
109
|
+
path = dirname(__file__) + "/sounds/portal"
|
|
110
|
+
files = [mp3 for mp3 in listdir(path) if ".mp3" in mp3]
|
|
111
|
+
if len(files):
|
|
112
|
+
mp3 = path + "/" + random.choice(files)
|
|
113
|
+
self.play_sound(mp3)
|
|
114
|
+
else:
|
|
115
|
+
self.speak_dialog("bad_file")
|
|
116
|
+
|
|
117
|
+
def handle_hal_intent(self, _):
|
|
118
|
+
path = dirname(__file__) + "/sounds/hal"
|
|
119
|
+
files = [mp3 for mp3 in listdir(path) if ".mp3" in mp3]
|
|
120
|
+
if len(files):
|
|
121
|
+
mp3 = path + "/" + random.choice(files)
|
|
122
|
+
self.play_sound(mp3)
|
|
123
|
+
else:
|
|
124
|
+
self.speak_dialog("bad_file")
|
|
125
|
+
|
|
126
|
+
def handle_dukenukem_intent(self, _):
|
|
127
|
+
path = dirname(__file__) + "/sounds/dukenukem"
|
|
128
|
+
files = [wav for wav in listdir(path) if ".wav" in wav]
|
|
129
|
+
if len(files):
|
|
130
|
+
wav = path + "/" + random.choice(files)
|
|
131
|
+
self.play_sound(wav)
|
|
132
|
+
else:
|
|
133
|
+
self.speak_dialog("bad_file")
|
|
134
|
+
|
|
135
|
+
def handle_arnold_intent(self, _):
|
|
136
|
+
path = dirname(__file__) + "/sounds/arnold"
|
|
137
|
+
files = [wav for wav in listdir(path) if ".wav" in wav]
|
|
138
|
+
if len(files):
|
|
139
|
+
wav = path + "/" + random.choice(files)
|
|
140
|
+
self.play_sound(wav)
|
|
141
|
+
else:
|
|
142
|
+
self.speak_dialog("bad_file")
|
|
143
|
+
|
|
144
|
+
def handle_bender_intent(self, _):
|
|
145
|
+
path = dirname(__file__) + "/sounds/bender"
|
|
146
|
+
files = [mp3 for mp3 in listdir(path) if ".mp3" in mp3]
|
|
147
|
+
if len(files):
|
|
148
|
+
mp3 = path + "/" + random.choice(files)
|
|
149
|
+
self.play_sound(mp3)
|
|
150
|
+
else:
|
|
151
|
+
self.speak_dialog("bad_file")
|
|
152
|
+
|
|
153
|
+
def handle_glados_intent(self, _):
|
|
154
|
+
path = dirname(__file__) + "/sounds/glados"
|
|
155
|
+
files = [mp3 for mp3 in listdir(path) if ".mp3" in mp3]
|
|
156
|
+
if len(files):
|
|
157
|
+
mp3 = path + "/" + random.choice(files)
|
|
158
|
+
self.play_sound(mp3)
|
|
159
|
+
else:
|
|
160
|
+
self.speak_dialog("bad_file")
|
|
161
|
+
|
|
162
|
+
def stop(self):
|
|
163
|
+
pass
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def create_skill():
|
|
167
|
+
return EasterEggsSkill()
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Redistribution and use in source and binary forms, with or without
|
|
2
|
+
# modification, are permitted provided that the following conditions are met:
|
|
3
|
+
# 1. Redistributions of source code must retain the above copyright notice,
|
|
4
|
+
# this list of conditions and the following disclaimer.
|
|
5
|
+
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
6
|
+
# this list of conditions and the following disclaimer in the documentation
|
|
7
|
+
# and/or other materials provided with the distribution.
|
|
8
|
+
# 3. Neither the name of the copyright holder nor the names of its
|
|
9
|
+
# contributors may be used to endorse or promote products derived from this
|
|
10
|
+
# software without specific prior written permission.
|
|
11
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
12
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
13
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
14
|
+
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
|
15
|
+
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
16
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
17
|
+
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
|
18
|
+
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
19
|
+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
20
|
+
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
21
|
+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
22
|
+
|
|
23
|
+
from setuptools import setup
|
|
24
|
+
from os import getenv, path, walk
|
|
25
|
+
|
|
26
|
+
SKILL_NAME = "skill-easter-eggs"
|
|
27
|
+
SKILL_PKG = SKILL_NAME.replace("-", "_")
|
|
28
|
+
# skill_id=package_name:SkillClass
|
|
29
|
+
PLUGIN_ENTRY_POINT = f"{SKILL_NAME}.openvoiceos={SKILL_PKG}:EasterEggsSkill"
|
|
30
|
+
BASE_PATH = path.abspath(path.dirname(__file__))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_requirements(requirements_filename: str):
|
|
34
|
+
requirements_file = path.join(BASE_PATH, requirements_filename)
|
|
35
|
+
with open(requirements_file, "r", encoding="utf-8") as r:
|
|
36
|
+
requirements = r.readlines()
|
|
37
|
+
requirements = [r.strip() for r in requirements if r.strip() and not r.strip().startswith("#")]
|
|
38
|
+
|
|
39
|
+
for i in range(0, len(requirements)):
|
|
40
|
+
r = requirements[i]
|
|
41
|
+
if "@" in r:
|
|
42
|
+
parts = [p.lower() if p.strip().startswith("git+http") else p for p in r.split("@")]
|
|
43
|
+
r = "@".join(parts)
|
|
44
|
+
if getenv("GITHUB_TOKEN"):
|
|
45
|
+
if "github.com" in r:
|
|
46
|
+
requirements[i] = r.replace("github.com", f"{getenv('GITHUB_TOKEN')}@github.com")
|
|
47
|
+
return requirements
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def find_resource_files():
|
|
51
|
+
resource_base_dirs = ("locale", "vocab", "dialog", "regex") # Removed "ui"
|
|
52
|
+
base_dir = BASE_PATH
|
|
53
|
+
package_data = ["skill.json"]
|
|
54
|
+
for res in resource_base_dirs:
|
|
55
|
+
if path.isdir(path.join(base_dir, res)):
|
|
56
|
+
for directory, _, files in walk(path.join(base_dir, res)):
|
|
57
|
+
if files:
|
|
58
|
+
package_data.append(path.join(directory.replace(base_dir, "").lstrip("/"), "*"))
|
|
59
|
+
# print(package_data)
|
|
60
|
+
return package_data
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
with open(path.join(BASE_PATH, "README.md"), "r") as f:
|
|
64
|
+
long_description = f.read()
|
|
65
|
+
|
|
66
|
+
with open(path.join(BASE_PATH, "version.py"), "r", encoding="utf-8") as v:
|
|
67
|
+
for line in v.readlines():
|
|
68
|
+
if line.startswith("__version__"):
|
|
69
|
+
if '"' in line:
|
|
70
|
+
version = line.split('"')[1]
|
|
71
|
+
else:
|
|
72
|
+
version = line.split("'")[1]
|
|
73
|
+
|
|
74
|
+
setup(
|
|
75
|
+
name=f"{SKILL_NAME}",
|
|
76
|
+
version=version,
|
|
77
|
+
url=f"https://github.com/OpenVoiceOS/{SKILL_NAME}",
|
|
78
|
+
license="BSD-3-Clause",
|
|
79
|
+
install_requires=get_requirements("requirements.txt"),
|
|
80
|
+
author="Jarbas",
|
|
81
|
+
author_email="jarbas@openvoiceos.com",
|
|
82
|
+
long_description=long_description,
|
|
83
|
+
long_description_content_type="text/markdown",
|
|
84
|
+
package_dir={SKILL_PKG: ""},
|
|
85
|
+
packages=[SKILL_PKG],
|
|
86
|
+
package_data={SKILL_PKG: find_resource_files()},
|
|
87
|
+
include_package_data=True,
|
|
88
|
+
entry_points={"ovos.plugin.skill": PLUGIN_ENTRY_POINT},
|
|
89
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: skill-easter-eggs
|
|
3
|
+
Version: 0.0.1a1
|
|
4
|
+
Summary: UNKNOWN
|
|
5
|
+
Home-page: https://github.com/OpenVoiceOS/skill-easter-eggs
|
|
6
|
+
Author: Jarbas
|
|
7
|
+
Author-email: jarbas@openvoiceos.com
|
|
8
|
+
License: BSD-3-Clause
|
|
9
|
+
Platform: UNKNOWN
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
|
|
13
|
+
## Easter Eggs
|
|
14
|
+
|
|
15
|
+
[](https://en.cryptobadges.io/donate/1QJNhKM8tVv62XSUrST2vnaMXh5ADSyYP8)
|
|
16
|
+
[](https://paypal.me/jarbasai)
|
|
17
|
+
<span class="badge-patreon"><a href="https://www.patreon.com/jarbasAI" title="Donate to this project using Patreon"><img src="https://img.shields.io/badge/patreon-donate-yellow.svg" alt="Patreon donate button" /></a></span>
|
|
18
|
+
[](https://saythanks.io/to/JarbasAl)
|
|
19
|
+
|
|
20
|
+
pop culture references skill
|
|
21
|
+
|
|
22
|
+
## Description
|
|
23
|
+
|
|
24
|
+
Some funny things for mycroft, mostly quotes from movies
|
|
25
|
+
|
|
26
|
+
## Examples
|
|
27
|
+
|
|
28
|
+
- "current stardate"
|
|
29
|
+
- "open the pod bay doors"
|
|
30
|
+
- "first law of robotics"
|
|
31
|
+
- "how to play rock_paper_scissors_lizard_spock"
|
|
32
|
+
- "how many languages do you speak"
|
|
33
|
+
- "do you like portal"
|
|
34
|
+
- "what would duke nukem say"
|
|
35
|
+
- "what would HAL 9000 say"
|
|
36
|
+
- "what would arnold say"
|
|
37
|
+
- "what would glados say"
|
|
38
|
+
- "what would bender say"
|
|
39
|
+
|
|
40
|
+
## Credits
|
|
41
|
+
|
|
42
|
+
JarbasAI
|
|
43
|
+
mikejgray (revival)
|
|
44
|
+
|
|
45
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
__init__.py
|
|
4
|
+
setup.py
|
|
5
|
+
stardate.py
|
|
6
|
+
version.py
|
|
7
|
+
skill_easter_eggs.egg-info/PKG-INFO
|
|
8
|
+
skill_easter_eggs.egg-info/SOURCES.txt
|
|
9
|
+
skill_easter_eggs.egg-info/dependency_links.txt
|
|
10
|
+
skill_easter_eggs.egg-info/entry_points.txt
|
|
11
|
+
skill_easter_eggs.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
skill_easter_eggs
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
# https://www.trekterest.com/stardatefaq.php
|
|
6
|
+
class Stardate:
|
|
7
|
+
# Definitions to help with leap years.
|
|
8
|
+
nrmdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
|
9
|
+
lyrdays = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
|
10
|
+
dayseconds = 86400
|
|
11
|
+
sdreg = re.compile(r"^\[(-{0,1}\d+)\](\d+)\.{1}(\d+)$")
|
|
12
|
+
datetimereg = re.compile(r"^(\d{4})-(\d{1,2})-(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$")
|
|
13
|
+
|
|
14
|
+
# The epoch for stardates, 2162-01-04, is 789294 (0xc0b2e) days after
|
|
15
|
+
# the internal epoch. This is 789294*86400 (0xc0b2e*0x15180) ==
|
|
16
|
+
# 68195001600 (0xfe0bd2500) seconds.
|
|
17
|
+
ufpepoch = 0xFE0BD2500
|
|
18
|
+
|
|
19
|
+
# The epoch for TNG-style stardates, 2323-01-01, is 848094 (0xcf0de)
|
|
20
|
+
# days after the internal epoch. This is 73275321600 (0x110f8cad00)
|
|
21
|
+
# seconds.
|
|
22
|
+
tngepoch = 0x110F8CAD00
|
|
23
|
+
|
|
24
|
+
def gleapyear(self, y):
|
|
25
|
+
return (not y % 4) and (y % 100 or not y % 400)
|
|
26
|
+
|
|
27
|
+
def gdays(self, y):
|
|
28
|
+
return self.lyrdays if self.gleapyear(y) else self.nrmdays
|
|
29
|
+
|
|
30
|
+
def __init__(self):
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
def toStardate(self, date=None):
|
|
34
|
+
S, F = 0, 0
|
|
35
|
+
if not date:
|
|
36
|
+
date = self.getcurdate()
|
|
37
|
+
date = list(re.findall(self.datetimereg, date)[0])
|
|
38
|
+
date = [int(i) for i in date]
|
|
39
|
+
S = self.gregin(date)
|
|
40
|
+
|
|
41
|
+
isneg = True
|
|
42
|
+
nissue, integer, frac = 0, 0, 0
|
|
43
|
+
|
|
44
|
+
if S >= self.tngepoch:
|
|
45
|
+
return self.toTngStardate(S, F)
|
|
46
|
+
|
|
47
|
+
if S < self.ufpepoch:
|
|
48
|
+
# negative stardate
|
|
49
|
+
diff = self.ufpepoch - S
|
|
50
|
+
nsecs = 2000 * self.dayseconds - 1 - (diff % (2000 * self.dayseconds))
|
|
51
|
+
isneg = True
|
|
52
|
+
nissue = 1 + ((diff / (2000 * self.dayseconds)) & 0xFFFFFFFF)
|
|
53
|
+
integer = nsecs / (self.dayseconds / 5)
|
|
54
|
+
frac = (((nsecs % (self.dayseconds / 5)) << 32) | F) * 50
|
|
55
|
+
elif S < self.tngepoch:
|
|
56
|
+
# positive stardate
|
|
57
|
+
diff = S - self.ufpepoch
|
|
58
|
+
nsecs = diff % (2000 * self.dayseconds)
|
|
59
|
+
isneg = False
|
|
60
|
+
nissue = (diff / (2000 * self.dayseconds)) & 0xFFFFFFFF
|
|
61
|
+
|
|
62
|
+
if nissue < 19 or (nissue == 19 and nsecs < (7340 * (self.dayseconds / 5))):
|
|
63
|
+
# TOS era
|
|
64
|
+
integer = nsecs / (self.dayseconds / 5)
|
|
65
|
+
frac = (((nsecs % (self.dayseconds / 5)) << 32) | F) * 50
|
|
66
|
+
else:
|
|
67
|
+
# film era
|
|
68
|
+
nsecs += (nissue - 19) * 2000 * self.dayseconds
|
|
69
|
+
nissue = 19
|
|
70
|
+
nsecs -= 7340 * (self.dayseconds / 5)
|
|
71
|
+
if nsecs >= 5000 * self.dayseconds:
|
|
72
|
+
# late film era
|
|
73
|
+
nsecs -= 5000 * self.dayseconds
|
|
74
|
+
integer = 7840 + nsecs / (self.dayseconds * 2)
|
|
75
|
+
if integer >= 10000:
|
|
76
|
+
integer -= 10000
|
|
77
|
+
nissue += 1
|
|
78
|
+
frac = (((nsecs % (self.dayseconds * 2)) << 32) | F) * 5
|
|
79
|
+
else:
|
|
80
|
+
# early film era
|
|
81
|
+
integer = 7340 + nsecs / (self.dayseconds * 10)
|
|
82
|
+
frac = ((nsecs % (self.dayseconds * 10)) << 32) | F
|
|
83
|
+
|
|
84
|
+
ret = "[" + ("-" if isneg else "") + str(nissue) + "]" + str(integer).zfill(4)
|
|
85
|
+
frac = (((frac * 125) / 108) >> 32) & 0xFFFFFFFF # round
|
|
86
|
+
ret += "." + str(frac)
|
|
87
|
+
return ret
|
|
88
|
+
|
|
89
|
+
def toTngStardate(self, S=0, F=0):
|
|
90
|
+
diff = S - self.tngepoch
|
|
91
|
+
# 1 issue is 86400*146097/4 seconds long, which just fits in 32 bits.
|
|
92
|
+
nissue = 21 + diff / ((self.dayseconds / 4) * 146097)
|
|
93
|
+
nsecs = diff % ((self.dayseconds / 4) * 146097)
|
|
94
|
+
# 1 unit is (86400*146097/4)/100000 seconds, which isn't even.
|
|
95
|
+
# It cancels to 27*146097/125. For a six-figure fraction,
|
|
96
|
+
# divide that by 1000000.
|
|
97
|
+
h = nsecs * 125000000
|
|
98
|
+
l = F * 125000000
|
|
99
|
+
h = h + ((l >> 32) & 0xFFFFFFFF)
|
|
100
|
+
h = h / (27 * 146097)
|
|
101
|
+
ret = "[%d]%05d" % (nissue, ((h / 1000000) & 0xFFFFFFFF))
|
|
102
|
+
ret += ".%06d" % (h % 1000000)
|
|
103
|
+
return ret
|
|
104
|
+
|
|
105
|
+
def getcurdate(self):
|
|
106
|
+
return datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
107
|
+
|
|
108
|
+
def gregin(self, date=None):
|
|
109
|
+
y, m, d, H, M, S = date
|
|
110
|
+
|
|
111
|
+
cycle = y % 400
|
|
112
|
+
|
|
113
|
+
low = y == 0
|
|
114
|
+
if low:
|
|
115
|
+
y = 399
|
|
116
|
+
else:
|
|
117
|
+
y = y - 1
|
|
118
|
+
|
|
119
|
+
t = y * 365
|
|
120
|
+
t = t - y / 100
|
|
121
|
+
t = t + y / 400
|
|
122
|
+
t = t + y / 4
|
|
123
|
+
|
|
124
|
+
n = 2 + d - 1
|
|
125
|
+
m -= 1
|
|
126
|
+
while m > 0:
|
|
127
|
+
n += self.gdays(cycle)[m]
|
|
128
|
+
m -= 1
|
|
129
|
+
|
|
130
|
+
t = t + n
|
|
131
|
+
if low:
|
|
132
|
+
t = t - 146097
|
|
133
|
+
t = t * self.dayseconds
|
|
134
|
+
|
|
135
|
+
retS = t + H * 3600 + M * 60 + S
|
|
136
|
+
|
|
137
|
+
return retS
|
|
138
|
+
|
|
139
|
+
def fromStardate(self, stardate):
|
|
140
|
+
nineteen = 19
|
|
141
|
+
twenty = 20
|
|
142
|
+
S, F = 0, 0
|
|
143
|
+
|
|
144
|
+
sd = re.findall(self.sdreg, stardate)
|
|
145
|
+
if not sd:
|
|
146
|
+
print("Invalid stardate format")
|
|
147
|
+
return
|
|
148
|
+
sd = sd[0]
|
|
149
|
+
nissue = int(sd[0])
|
|
150
|
+
isneg = nissue < 0
|
|
151
|
+
nissue = abs(nissue)
|
|
152
|
+
integer = int(sd[1])
|
|
153
|
+
frac = int(sd[2] + "0" * (6 - len(sd[2])))
|
|
154
|
+
|
|
155
|
+
if (
|
|
156
|
+
(integer > 99999)
|
|
157
|
+
or (not isneg and nissue == twenty and integer > 5005)
|
|
158
|
+
or ((isneg or nissue < twenty) and integer > 9999)
|
|
159
|
+
):
|
|
160
|
+
print("Integer part is out of range")
|
|
161
|
+
return
|
|
162
|
+
|
|
163
|
+
if isneg or nissue <= twenty:
|
|
164
|
+
# Pre-TNG stardate
|
|
165
|
+
if not isneg:
|
|
166
|
+
# There are two changes in stardate rate to handle:
|
|
167
|
+
# up to [19]7340 0.2 days/unit
|
|
168
|
+
# [19]7340 to [19]7840 10 days/unit
|
|
169
|
+
# [19]7840 to [20]5006 2 days/unit
|
|
170
|
+
# we scale to the first of these.
|
|
171
|
+
|
|
172
|
+
fiddle = False
|
|
173
|
+
if nissue == twenty:
|
|
174
|
+
nissue = nineteen
|
|
175
|
+
integer += 10000
|
|
176
|
+
fiddle = True
|
|
177
|
+
elif nissue == nineteen and integer >= 7340:
|
|
178
|
+
fiddle = True
|
|
179
|
+
|
|
180
|
+
if fiddle:
|
|
181
|
+
# We have a stardate in the range [19]7340 to [19]15006. First
|
|
182
|
+
# we scale it to match the prior rate, so this range changes to
|
|
183
|
+
# 7340 to 390640.
|
|
184
|
+
integer = 7340 + ((integer - 7340) * 50) + frac / (1000000 / 50)
|
|
185
|
+
frac = (frac * 50) % 1000000
|
|
186
|
+
|
|
187
|
+
# Next, if the stardate is greater than what was originally
|
|
188
|
+
# [19]7840 (now represented as 32340), it is in the 2 days/unit
|
|
189
|
+
# range, so scale it back again. The range affected, 32340 to
|
|
190
|
+
# 390640, changes to 32340 to 104000.
|
|
191
|
+
if integer >= 32340:
|
|
192
|
+
frac = frac / 5 + (integer % 5) * (1000000 / 5)
|
|
193
|
+
integer = 32340 + (integer - 32340) / 5
|
|
194
|
+
|
|
195
|
+
S = self.ufpepoch + nissue * 2000 * self.dayseconds
|
|
196
|
+
|
|
197
|
+
else:
|
|
198
|
+
# Negative stardate. In order to avoid underflow in some cases, we
|
|
199
|
+
# actually calculate a date one issue (2000 days) too late, and
|
|
200
|
+
# then subtract that much as the last stage.
|
|
201
|
+
S = self.ufpepoch - (nissue - 1) * 2000 * self.dayseconds
|
|
202
|
+
|
|
203
|
+
S = S + (self.dayseconds / 5) * integer
|
|
204
|
+
|
|
205
|
+
# frac is scaled such that it is in the range 0-999999, and a value
|
|
206
|
+
# of 1000000 would represent 86400/5 seconds. We want to put frac
|
|
207
|
+
# in the top half of a uint64, multiply by 86400/5 and divide by
|
|
208
|
+
# 1000000, in order to leave the uint64 containing (top half) a
|
|
209
|
+
# number of seconds and (bottom half) a fraction. In order to
|
|
210
|
+
# avoid overflow, this scaling is cancelled down to a multiply by
|
|
211
|
+
# 54 and a divide by 3125.
|
|
212
|
+
f = (frac << 32) * 54
|
|
213
|
+
f = (f + 3124) / 3125
|
|
214
|
+
S = S + ((f >> 32) & 0xFFFFFFFF)
|
|
215
|
+
F = f & 0xFFFFFFFF
|
|
216
|
+
|
|
217
|
+
if isneg:
|
|
218
|
+
# Subtract off the issue that was added above.
|
|
219
|
+
S = S - 2000 * self.dayseconds
|
|
220
|
+
|
|
221
|
+
else:
|
|
222
|
+
# TNG stardate
|
|
223
|
+
nissue = nissue - 21
|
|
224
|
+
|
|
225
|
+
# Each issue is 86400*146097/4 seconds long.
|
|
226
|
+
S = self.tngepoch + nissue * (self.dayseconds / 4) * 146097
|
|
227
|
+
|
|
228
|
+
# 1 unit is (86400*146097/4)/100000 seconds, which isn't even.
|
|
229
|
+
# It cancels to 27146097/125.
|
|
230
|
+
t = integer * 1000000
|
|
231
|
+
t = t + frac
|
|
232
|
+
t = t * 27 * 146097
|
|
233
|
+
S = S + t / 125000000
|
|
234
|
+
|
|
235
|
+
t = (t % 125000000) << 32
|
|
236
|
+
t = (t + 124999999) / 125000000
|
|
237
|
+
F = t & 0xFFFFFFFF
|
|
238
|
+
|
|
239
|
+
return self.calout(S, F)
|
|
240
|
+
|
|
241
|
+
def calout(self, S=0, F=0):
|
|
242
|
+
tod = S % self.dayseconds
|
|
243
|
+
days = S / self.dayseconds
|
|
244
|
+
|
|
245
|
+
# We need the days number to be days since an xx01.01.01 to get the
|
|
246
|
+
# leap year cycle right. For the Julian calendar, it is already
|
|
247
|
+
# so (0001=01=01). But for the Gregorian calendar, the epoch is
|
|
248
|
+
# 0000-12-30, so we must add on 400 years minus 2 days. The year
|
|
249
|
+
# number gets corrected below.
|
|
250
|
+
days = days + 146095
|
|
251
|
+
|
|
252
|
+
# Approximate the year number, underestimating but only by a limited
|
|
253
|
+
# amount. days/366 is a first approximation, but it goes out by 1
|
|
254
|
+
# day every non-leap year, and so will be a full year out after 366
|
|
255
|
+
# non-leap years. In the Julian calendar, we get 366 non-leap years
|
|
256
|
+
# every 488 years, so adding (days/366)/487 corrects for this. In
|
|
257
|
+
# the Gregorian calendar, it is not so simple: we get 400 years
|
|
258
|
+
# every 146097 days, and then add on days/366 within that set of 400
|
|
259
|
+
# years.
|
|
260
|
+
year = (days / 146097) * 400 + (days % 146097) / 366
|
|
261
|
+
|
|
262
|
+
# We then adjust the number of days remaining to match this
|
|
263
|
+
# approximation of the year. Note that this approximation
|
|
264
|
+
# will never be more than two years off the correct date,
|
|
265
|
+
# so the number of days left no longer needs to be stored
|
|
266
|
+
# in a uint64.
|
|
267
|
+
days = (days + year / 100) - (year / 400)
|
|
268
|
+
days = days - (year * 365 + year / 4)
|
|
269
|
+
|
|
270
|
+
# Now correct the year to an actual year number (see notes above).
|
|
271
|
+
year = year - 399
|
|
272
|
+
|
|
273
|
+
return self.docalout(year % 400, year, days & 0xFFFFFFFF, tod)
|
|
274
|
+
|
|
275
|
+
def docalout(self, cycle, year, ndays, tod):
|
|
276
|
+
nmonth = 0
|
|
277
|
+
# Walk through the months, fixing the year, and as a side effect
|
|
278
|
+
# calculating the month number and day of the month.
|
|
279
|
+
while ndays >= self.gdays(cycle)[nmonth]:
|
|
280
|
+
ndays -= self.gdays(cycle)[nmonth]
|
|
281
|
+
nmonth += 1
|
|
282
|
+
if nmonth == 12:
|
|
283
|
+
nmonth = 0
|
|
284
|
+
year += 1
|
|
285
|
+
cycle += 1
|
|
286
|
+
|
|
287
|
+
ndays += 1
|
|
288
|
+
nmonth += 1
|
|
289
|
+
# Now sort out the time of day.
|
|
290
|
+
hr = tod / 3600
|
|
291
|
+
tod %= 3600
|
|
292
|
+
minut = tod / 60
|
|
293
|
+
sec = tod % 60
|
|
294
|
+
|
|
295
|
+
return "%d-%02d-%02d %d:%d:%d" % (year, nmonth, ndays, hr, minut, sec)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.0.1a1"
|