Merge branch 'develop' into wip/rect_rework

This commit is contained in:
Jörn-Michael Miehe 2023-09-22 23:48:17 +00:00
commit 6cbb15dc69
6 changed files with 136 additions and 12 deletions

View file

@ -3,7 +3,7 @@ import random
import re import re
from datetime import date, datetime, timedelta from datetime import date, datetime, timedelta
from io import BytesIO from io import BytesIO
from typing import Any, Self, Sequence, TypeVar from typing import Any, Iterable, Self, Sequence, TypeVar
from fastapi.responses import StreamingResponse from fastapi.responses import StreamingResponse
from PIL import Image from PIL import Image
@ -32,6 +32,53 @@ def set_len(seq: Sequence[T], len: int) -> Sequence[T]:
return list(itertools.islice(infinite, len)) return list(itertools.islice(infinite, len))
def spread(
given: Iterable[int],
n: int,
rnd: Random | None = None,
) -> list[int]:
"""
Zu `given` ganzen Zahlen `n` zusätzliche Zahlen hinzunehmen.
- Die neuen Werte sind im selben Zahlenbereich wie `given`
- Zuerst werden alle Werte "zwischen" den `given` Werten genommen
"""
if n == 0:
return []
if len(set(given)) > 1:
range_given = range(min(given), max(given) + 1)
first_round = set(range_given) - set(given)
elif len(set(given)) == 1:
if (a := next(iter(given))) > 0:
range_given = range(1, a + 1)
else:
range_given = range(1, n + 1)
first_round = set(range_given) - set(given)
else:
range_given = range(1, n + 1)
first_round = range_given
result = sorted(first_round)[: min(n, len(first_round))]
full_rounds = (n - len(result)) // len(range_given)
result += list(range_given) * full_rounds
remain = n - len(result)
if rnd is None:
result += list(range_given)[:remain]
else:
result += rnd.sample(range_given, remain)
rnd.shuffle(result)
return result
async def list_images_auto() -> list[str]: async def list_images_auto() -> list[str]:
""" """
Finde alle Bilddateien im "automatisch"-Verzeichnis Finde alle Bilddateien im "automatisch"-Verzeichnis

77
api/test/test_spread.py Normal file
View file

@ -0,0 +1,77 @@
from advent22_api.core.helpers import spread
def test_easy() -> None:
assert spread([1, 4], 0) == []
assert spread([1, 4], 1) == [2]
assert spread([1, 4], 2) == [2, 3]
assert spread([1, 4], 5) == [2, 3, 1, 2, 3]
assert spread([1, 4], 10) == [2, 3, 1, 2, 3, 4, 1, 2, 3, 4]
def test_tight() -> None:
assert spread([1, 2], 0) == []
assert spread([1, 2], 1) == [1]
assert spread([1, 2], 2) == [1, 2]
assert spread([1, 2], 5) == [1, 2, 1, 2, 1]
assert spread([1, 2], 10) == [1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
assert spread([1, 2, 3, 4, 5], 0) == []
assert spread([1, 2, 3, 4, 5], 1) == [1]
assert spread([1, 2, 3, 4, 5], 2) == [1, 2]
assert spread([1, 2, 3, 4, 5], 5) == [1, 2, 3, 4, 5]
assert spread([1, 2, 3, 4, 5], 10) == [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]
def test_more_given() -> None:
assert spread([0, 5, 10], 0) == []
assert spread([0, 5, 10], 1) == [1]
assert spread([0, 5, 10], 2) == [1, 2]
assert spread([0, 5, 10], 5) == [1, 2, 3, 4, 6]
assert spread([0, 5, 10], 10) == [1, 2, 3, 4, 6, 7, 8, 9, 0, 1]
assert spread([0, 1, 2, 5, 10], 0) == []
assert spread([0, 1, 2, 5, 10], 1) == [3]
assert spread([0, 1, 2, 5, 10], 2) == [3, 4]
assert spread([0, 1, 2, 5, 10], 5) == [3, 4, 6, 7, 8]
assert spread([0, 1, 2, 5, 10], 10) == [3, 4, 6, 7, 8, 9, 0, 1, 2, 3]
def test_one_given() -> None:
assert spread([0], 0) == []
assert spread([0], 1) == [1]
assert spread([0], 2) == [1, 2]
assert spread([0], 5) == [1, 2, 3, 4, 5]
assert spread([0], 10) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
assert spread([1], 0) == []
assert spread([1], 1) == [1]
assert spread([1], 2) == [1, 1]
assert spread([1], 5) == [1, 1, 1, 1, 1]
assert spread([1], 10) == [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
assert spread([2], 0) == []
assert spread([2], 1) == [1]
assert spread([2], 2) == [1, 1]
assert spread([2], 5) == [1, 1, 2, 1, 2]
assert spread([2], 10) == [1, 1, 2, 1, 2, 1, 2, 1, 2, 1]
assert spread([5], 0) == []
assert spread([5], 1) == [1]
assert spread([5], 2) == [1, 2]
assert spread([5], 5) == [1, 2, 3, 4, 1]
assert spread([5], 10) == [1, 2, 3, 4, 1, 2, 3, 4, 5, 1]
assert spread([10], 0) == []
assert spread([10], 1) == [1]
assert spread([10], 2) == [1, 2]
assert spread([10], 5) == [1, 2, 3, 4, 5]
assert spread([10], 10) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 1]
def test_none_given() -> None:
assert spread([], 0) == []
assert spread([], 1) == [1]
assert spread([], 2) == [1, 2]
assert spread([], 5) == [1, 2, 3, 4, 5]
assert spread([], 10) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

View file

@ -23,10 +23,7 @@
</div> </div>
<div class="level-right"> <div class="level-right">
<div class="level-item"> <div class="level-item">
<AdminButton <AdminButton class="tag is-link is-outlined" v-model="is_admin" />
v-model="is_admin"
button_class="tag is-link is-outlined"
/>
</div> </div>
</div> </div>
</nav> </nav>

View file

@ -2,7 +2,7 @@
<LoginModal v-if="modal_visible" @submit="on_submit" @cancel="on_cancel" /> <LoginModal v-if="modal_visible" @submit="on_submit" @cancel="on_cancel" />
<BulmaButton <BulmaButton
:class="button_class" v-bind="$attrs"
:icon="'fa-solid fa-toggle-' + (modelValue ? 'on' : 'off')" :icon="'fa-solid fa-toggle-' + (modelValue ? 'on' : 'off')"
:busy="is_busy" :busy="is_busy"
text="Admin" text="Admin"
@ -11,6 +11,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Credentials } from "@/lib/api";
import { Options, Vue } from "vue-class-component"; import { Options, Vue } from "vue-class-component";
import BulmaButton from "./bulma/Button.vue"; import BulmaButton from "./bulma/Button.vue";
@ -23,14 +24,12 @@ import LoginModal from "./LoginModal.vue";
}, },
props: { props: {
modelValue: Boolean, modelValue: Boolean,
button_class: String,
}, },
emits: ["update:modelValue"], emits: ["update:modelValue"],
}) })
export default class extends Vue { export default class extends Vue {
// true, iff Benutzer Admin ist // true, iff Benutzer Admin ist
public modelValue!: boolean; public modelValue!: boolean;
public button_class!: string;
public modal_visible = false; public modal_visible = false;
public is_busy = false; public is_busy = false;
@ -38,7 +37,7 @@ export default class extends Vue {
public on_click() { public on_click() {
if (this.modelValue) { if (this.modelValue) {
// logout // logout
this.$advent22.set_api_auth(); this.$advent22.clear_api_auth();
this.$emit("update:modelValue", false); this.$emit("update:modelValue", false);
} else { } else {
// show login modal // show login modal
@ -47,9 +46,9 @@ export default class extends Vue {
} }
} }
public on_submit(username: string, password: string) { public on_submit(creds: Credentials) {
this.modal_visible = false; this.modal_visible = false;
this.$advent22.api_auth = [username, password]; this.$advent22.api_auth = creds;
this.$advent22 this.$advent22
.api_get<boolean>("admin/is_admin") .api_get<boolean>("admin/is_admin")

View file

@ -89,7 +89,7 @@ export default class extends Vue {
} }
public submit(): void { public submit(): void {
this.$emit("submit", this.username, this.password); this.$emit("submit", [this.username, this.password]);
} }
public cancel(): void { public cancel(): void {

View file

@ -94,6 +94,10 @@ export class Advent22 {
this._api_auth = creds; this._api_auth = creds;
} }
public clear_api_auth(): void {
this.set_api_auth();
}
public set api_auth(creds: Credentials) { public set api_auth(creds: Credentials) {
this.set_api_auth(creds); this.set_api_auth(creds);
} }