Skip to content

Meg interest calculator #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Nov 19, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
242 changes: 94 additions & 148 deletions poetry.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ typeguard = ">=2.13.3"
xdoctest = { extras = ["colors"], version = ">=0.15.10" }
myst-parser = { version = ">=0.16.1" }
requests = "^2.28.1"
playwright = "^1.27"
pytest-playwright = "^0.3.0"
pytest-asyncio-cooperative = "^0.28.0"
nox-poetry = "^1.0.1"
Expand Down
49 changes: 49 additions & 0 deletions src/psc/fixtures.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Automate some testing."""
from __future__ import annotations

import builtins
from dataclasses import dataclass
from dataclasses import field
from mimetypes import guess_type
Expand Down Expand Up @@ -180,3 +181,51 @@ def _route_handler(route: Route) -> None:
# Don't spend 30 seconds on timeout
page.set_default_timeout(12000)
return page


@dataclass
class FakeDocument:
"""Pretend to be a DOM that holds values at id's."""

values: dict[str, str] = field(default_factory=dict)
log: list[str] = field(default_factory=list)


@pytest.fixture
def fake_document() -> FakeDocument:
"""Yield a document that cleans up."""
yield FakeDocument()


@dataclass
class ElementNode:
value: str
document: FakeDocument

def write(self, value: str) -> None:
"""Collect anything that is written to the node."""
self.document.log.append(value)

def removeAttribute(self, name) -> None:
"""Pretend to remove an attribute from this node."""
pass


@dataclass
class ElementCallable:
document: FakeDocument

def __call__(self, key: str) -> ElementNode:
value = self.document.values[key]
node = ElementNode(value, self.document)
return node


@pytest.fixture
def fake_element(fake_document) -> None:
"""Install the stateful Element into builtins."""
try:
builtins.Element = ElementCallable(fake_document)
yield
finally:
delattr(builtins, "Element")
4 changes: 1 addition & 3 deletions src/psc/gallery/examples/hello_world_py/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
<link rel="stylesheet" href="hello_world.css">
</head>
<body>
<py-config src="../py_config.toml">
paths = ["hello_world.py"]
</py-config>
<py-config src="../py_config.toml"></py-config>
<main>
<h1>Hello Python ...</h1>
<div id="output"></div>
Expand Down
24 changes: 24 additions & 0 deletions src/psc/gallery/examples/interest_calculator/calculator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
def interest(*args, **kwargs):
# Signal that PyScript is alive by setting the ``Calculate``
# button away from disabled.
ec = Element("calc") # noqa

# Now get the various inputs
ep = Element("principal") # noqa
er = Element("interest_rate") # noqa
et = Element("time") # noqa
p = float(ep.value)
r = float(er.value)
t = float(et.value)
output1 = Element("simple_interest") # noqa
output2 = Element("compound_interest") # noqa
res1 = round(p + (p * r * t))
res2 = round(p * ((1 + r) ** t))
output1.write("simple interest: " + str(res1))
output2.write("compound interest: " + str(res2))


def setup():
"""When Pyodide starts up, enable the Calculate button."""
ec = Element("calc") # noqa
ec.element.removeAttribute("disabled")
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
96 changes: 96 additions & 0 deletions src/psc/gallery/examples/interest_calculator/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta charset="utf-8"/>
<title>Interest Calculator</title>
<link rel="stylesheet" href="styles.css"/>
<script defer src="../../../pyscript/pyscript.js"></script>
</head>

<body>

<header>
<h1 id="header_h1">Welcome to the Compound Calculator!</h1>
</header>

<main style="">

<div class="flexelement" id="first_div">
<p id="first_p">
Welcome to the "Simple and Compound Interest Calculator!"
<br/>
<strong>"how does it work?"</strong>
to use the "Simple and Compound Interest Calculator", please enter the input data into the form.
after clicking "Calculate", your result will be shown at the bottom of the form.
</p>

<div style="margin-left: 15%;">
<div style="width: 100%;">
<input type="radio" name='expander' id="expander-1">
<label class="expander_label" for="expander-1">Compound Interest Formula &#187;</label>
<img src="compound-interest.png" alt="Compound Interest"
style="height: 200px;"/>
</div>

<div style="margin-top: 25px;">
<input type="radio" name='expander' id="expander-2">
<label class="expander_label" for="expander-2">Simple Interest Formula &#187;</label>
<img src="simple-interest.png" alt="Simple Interest"
style="height: 150px;"/>
</div>
</div>
</div>


<div class="flexelement">

<div id="form" style="">

<div>
<label>Principal
<input id="principal" type="number" style="color: black; min-height: 60px;"/></label>
<br/><br>
<label>Interest rate
<input id="interest_rate" type="number" style="color: black; min-height: 60px;"
placeholder="Decimal, f.e. 0.8"/>
</label>
<br>
<br/>

<label>Time
<input id="time" type="number" style="color: black; min-height: 60px;"
placeholder="in years"/></label>
<br> <br/>

<button py-click="interest()" id="calc" style="min-height: 60px;" disabled>Calculate</button>

<div style="margin-top: 2%;">
<span id="simple_interest"></span>
<br/>
<span id="compound_interest"></span>
</div>

</div>

</div>

</div>

<py-config src="../py_config.toml"></py-config>
<py-script src="calculator.py"></py-script>
<py-script>
setup()
</py-script>
</main>

<footer>
<p id="footer_p">
thank you for using the "Simple and Compound
Interest Calculator!", powered by PyScript!
</p>
</footer>

</body>

</html>
5 changes: 5 additions & 0 deletions src/psc/gallery/examples/interest_calculator/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
title: Compound Interest Calculator
subtitle: The classic hello world, but in Python -- in a browser!
---
The *body* description.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
165 changes: 165 additions & 0 deletions src/psc/gallery/examples/interest_calculator/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
body {
background-color: #F3F6F8;
min-height: 100vh;
display: flex;
flex-direction: column;
}

main {
display: flex;
flex-direction: row;
}

img {
flex: 1;
margin: 5%;
margin-left: 20%;
}

#first_div {
align-content: center;
margin: 1%;
flex: 1.25;
}

#first_p {
margin: 3.5%;
margin-left: 15%;
font-family: Tahoma, sans-serif;
}

.flexelement {
flex: 1;
padding: 2%;
}



#form {
margin-top: 7%;
height: 100%;
display: flex;
align-content: center;
justify-content: center;
}

#form input[type=number] {
border: 1px solid white;
border-radius: 0.3em;
height: 12%;
width: 100%;
margin-bottom: 5px;
}


#form button {
width: 100%;
height: 12%;
margin-bottom: 5px;
}

header {
height: 100px;
}

footer {
margin-top: auto;
height: 57px;
}

header, footer {
background-color: #1A1A27;
}

#header_h1 {
padding-top: 2.2%;
margin-left: 40%;
font-weight: bold;
color: white;
}

input[type=number] {
padding: 1%;
}

#principal, #interest_rate, #time {
width: 25%;
}

#calc {
width: 25%;
padding: 1%;
font-weight: bold;
margin-top: 2%;
color: white;
background-color: #0095E8;
}

#simple_interest, #compound_interest {
color: black;
font-weight: bold;
}

input[type=radio] {
display: none;
}

label {
cursor: pointer;
}

input[type=radio] ~ img {
animation: close 1.5;
display: none;
height: 0;
max-height: 500px;
overflow: hidden;
}

input[type=radio]:checked ~ img {
animation: open 1.5s;
display: block;
height: auto;
max-height: 500px;
}

@keyframes open {
from {
max-height: 0;
}

to {
max-height: auto;
}
}

@keyframes close {
from {
display: block;
max-height: auto;
}

to {
display: none;
height: 0;
}
}

.expander_label {
border: 1px solid #0095E8;
border-radius: 0.1em;
padding: 1%;
font-weight: 500;
color: white;
background-color: #0095E8;
background-color: #0095E8;
}

#footer_p {
font-weight: bold;
font-size: 13px;
text-align: center;
color: white;
vertical-align: central;
padding: 1.2%;
}
Loading