dingus ocringus

This commit is contained in:
Anna 2022-09-03 08:59:06 -04:00
parent 216a62708e
commit cef98173e3
10 changed files with 183 additions and 21 deletions

View File

@ -64,8 +64,7 @@
</ItemGroup>
<ItemGroup>
<None Remove="elden-ring.yaml"/>
<EmbeddedResource Include="elden-ring.yaml"/>
<EmbeddedResource Include="../server/packs/*.yaml" LinkBase="packs"/>
</ItemGroup>
</Project>

View File

@ -1,7 +1,29 @@
using YamlDotNet.Serialization.NamingConventions;
namespace OrangeGuidanceTomestone;
[Serializable]
public class Pack {
internal static Lazy<Pack[]> All { get; } = new(() => {
var des = new YamlDotNet.Serialization.DeserializerBuilder()
.WithNamingConvention(UnderscoredNamingConvention.Instance)
.Build();
return new[] {
"ffxiv",
"elden-ring",
"dark-souls",
}
.Select(name => {
try {
return des.Deserialize<Pack>(Resourcer.Resource.AsString($"{name}.yaml"));
} catch {
return null;
}
})
.Where(pack => pack != null)
.ToArray()!;
});
public string Name { get; init; }
public Guid Id { get; init; }
public string[] Templates { get; init; }

View File

@ -1,6 +1,5 @@
using System.Text;
using ImGuiNET;
using YamlDotNet.Serialization.NamingConventions;
namespace OrangeGuidanceTomestone;
@ -33,14 +32,40 @@ public class PluginUi : IDisposable {
return;
}
var packPrev = Pack.All.Value[this._pack].Name;
if (ImGui.BeginCombo("Pack", packPrev)) {
for (var i = 0; i < Pack.All.Value.Length; i++) {
var selPack = Pack.All.Value[i];
if (!ImGui.Selectable(selPack.Name)) {
continue;
}
this._pack = i;
this._part1 = -1;
this._word1 = (-1, -1);
this._conj = -1;
this._part2 = -1;
this._word2 = (-1, -1);
}
ImGui.EndCombo();
}
const string placeholder = "****";
void DrawPicker(string id, IReadOnlyList<string> items, ref int x) {
var preview = x == -1 ? "" : items[x].Replace("{0}", "****");
var preview = x == -1 ? "" : items[x].Replace("{0}", placeholder);
if (!ImGui.BeginCombo(id, preview)) {
return;
}
if (ImGui.Selectable("<none>")) {
x = -1;
}
for (var i = 0; i < items.Count; i++) {
var template = items[i].Replace("{0}", "****");
var template = items[i].Replace("{0}", placeholder);
if (ImGui.Selectable(template, i == x)) {
x = i;
}
@ -73,18 +98,15 @@ public class PluginUi : IDisposable {
ImGui.EndCombo();
}
var pack = new YamlDotNet.Serialization.DeserializerBuilder()
.WithNamingConvention(UnderscoredNamingConvention.Instance)
.Build()
.Deserialize<Pack>(Resourcer.Resource.AsString("elden-ring.yaml"));
var pack = Pack.All.Value[this._pack];
if (this._part1 == -1) {
ImGui.TextUnformatted("****");
ImGui.TextUnformatted(placeholder);
} else {
var preview = new StringBuilder();
var template1 = pack.Templates[this._part1];
var word1 = this._word1 == (-1, -1) ? "****" : pack.Words[this._word1.Item1].Words[this._word1.Item2];
var word1 = this._word1 == (-1, -1) ? placeholder : pack.Words[this._word1.Item1].Words[this._word1.Item2];
preview.Append(string.Format(template1, word1));
if (this._conj != -1) {
@ -98,7 +120,7 @@ public class PluginUi : IDisposable {
if (this._part2 != -1) {
var template2 = pack.Templates[this._part2];
var word2 = this._word2 == (-1, -1) ? "****" : pack.Words[this._word2.Item1].Words[this._word2.Item2];
var word2 = this._word2 == (-1, -1) ? placeholder : pack.Words[this._word2.Item1].Words[this._word2.Item2];
preview.Append(string.Format(template2, word2));
}
}
@ -109,12 +131,90 @@ public class PluginUi : IDisposable {
ImGui.Separator();
DrawPicker("Template##part-1", pack.Templates, ref this._part1);
DrawWordPicker("Word##word-1", pack.Words, ref this._word1);
DrawPicker("Conjugation##conj", pack.Conjunctions, ref this._conj);
DrawPicker("Template##part-2", pack.Templates, ref this._part2);
DrawWordPicker("Word##word-2", pack.Words, ref this._word2);
if (this._part1 > -1 && pack.Templates[this._part1].Contains("{0}")) {
DrawWordPicker("Word##word-1", pack.Words, ref this._word1);
}
DrawPicker("Conjunction##conj", pack.Conjunctions, ref this._conj);
if (this._conj != -1) {
DrawPicker("Template##part-2", pack.Templates, ref this._part2);
if (this._part2 > -1 && pack.Templates[this._part2].Contains("{0}")) {
DrawWordPicker("Word##word-2", pack.Words, ref this._word2);
}
}
this.ClearIfNecessary();
var valid = this.ValidSetup();
if (valid) {
ImGui.BeginDisabled();
}
if (ImGui.Button("Write") && valid) {
}
if (valid) {
ImGui.EndDisabled();
}
ImGui.End();
}
private void ClearIfNecessary() {
if (this._pack == -1) {
this._part1 = -1;
}
var pack = Pack.All.Value[this._pack];
if (this._part1 == -1 || !pack.Templates[this._part1].Contains("{0}")) {
this._word1 = (-1, -1);
}
if (this._conj == -1) {
this._part2 = -1;
}
if (this._part2 == -1 || !pack.Templates[this._part2].Contains("{0}")) {
this._word2 = (-1, -1);
}
}
private bool ValidSetup() {
if (this._pack == -1 || this._part1 == -1) {
return false;
}
var pack = Pack.All.Value[this._pack];
var template1 = pack.Templates[this._part1];
var temp1Variable = template1.Contains("{0}");
switch (temp1Variable) {
case true when this._word1 == (-1, -1):
case false when this._word1 != (-1, -1):
return false;
}
if (this._conj == -1 && (this._part2 != -1 || this._word2 != (-1, -1))) {
return false;
}
if (this._conj != -1) {
if (this._part2 == -1) {
return false;
}
var template2 = pack.Templates[this._part2];
var temp2Variable = template2.Contains("{0}");
switch (temp2Variable) {
case true when this._word2 == (-1, -1):
case false when this._word2 != (-1, -1):
return false;
}
}
return true;
}
}

1
server/.env Normal file
View File

@ -0,0 +1 @@
DATABASE_URL="sqlite://database.sqlite"

1
server/.gitignore vendored
View File

@ -1,2 +1,3 @@
/target
/database.sqlite*
/config.toml

10
server/Cargo.lock generated
View File

@ -1038,6 +1038,7 @@ dependencies = [
"sha3",
"sqlx",
"tokio",
"toml",
"uuid",
"warp",
]
@ -1388,6 +1389,15 @@ dependencies = [
"tracing",
]
[[package]]
name = "toml"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
dependencies = [
"serde",
]
[[package]]
name = "tower-service"
version = "0.3.2"

View File

@ -13,6 +13,7 @@ serde = { version = "1", features = ["derive"] }
serde_yaml = "0.9"
sha3 = "0.10"
sqlx = { version = "0.6", features = ["runtime-tokio-rustls", "sqlite", "chrono"] }
toml = "0.5"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
uuid = { version = "1", features = ["serde", "v4"] }
warp = "0.3"

11
server/src/config.rs Normal file
View File

@ -0,0 +1,11 @@
use std::net::SocketAddr;
use std::path::PathBuf;
use serde::Deserialize;
#[derive(Debug, Deserialize)]
pub struct Config {
pub address: SocketAddr,
pub packs: PathBuf,
pub database: String,
}

View File

@ -1,7 +1,6 @@
#![feature(let_chains)]
use std::collections::HashMap;
use std::net::SocketAddr;
use std::sync::Arc;
use anyhow::{Context, Result};
@ -11,16 +10,19 @@ use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
use tokio::sync::RwLock;
use uuid::Uuid;
use crate::config::Config;
use crate::pack::Pack;
mod pack;
mod message;
mod web;
mod util;
mod config;
static MIGRATOR: Migrator = sqlx::migrate!();
pub struct State {
pub config: Config,
pub db: Pool<Sqlite>,
pub packs: RwLock<HashMap<Uuid, Pack>>,
}
@ -29,7 +31,7 @@ impl State {
pub async fn update_packs(&self) -> Result<()> {
let mut packs = HashMap::new();
let mut dir = tokio::fs::read_dir("packs").await?;
let mut dir = tokio::fs::read_dir(&self.config.packs).await?;
while let Ok(Some(entry)) = dir.next_entry().await {
if !entry.path().is_file() {
continue;
@ -64,6 +66,18 @@ impl State {
#[tokio::main]
async fn main() -> Result<()> {
let args: Vec<String> = std::env::args().skip(1).collect();
if args.is_empty() {
eprintln!("usage: server [config]");
return Ok(());
}
let config_str = tokio::fs::read_to_string(&args[0])
.await
.with_context(|| format!("could not read config file at {}", args[0]))?;
let config: Config = toml::from_str(&config_str)
.context("could not parse config file")?;
let options = SqliteConnectOptions::new();
// options.log_statements(LevelFilter::Debug);
@ -76,7 +90,7 @@ async fn main() -> Result<()> {
Ok(())
}))
// .connect_with(options.filename(&config.database.path))
.connect_with(options.filename("./database.sqlite"))
.connect_with(options.filename(&config.database))
.await
.context("could not connect to database")?;
MIGRATOR.run(&pool)
@ -84,12 +98,14 @@ async fn main() -> Result<()> {
.context("could not run database migrations")?;
let state = Arc::new(State {
config,
db: pool,
packs: Default::default(),
});
state.update_packs().await?;
warp::serve(web::routes(state)).run("127.0.0.1:8080".parse::<SocketAddr>()?).await;
let address = state.config.address.clone();
warp::serve(web::routes(state)).run(address).await;
Ok(())
}

View File

@ -30,10 +30,11 @@ async fn logic(state: Arc<State>, id: i64, message_id: Uuid, vote: i8) -> Result
};
sqlx::query!(
// language=sqlite
"insert or ignore into votes (user, message, vote) values (?, ?, ?)",
"insert into votes (user, message, vote) values (?, ?, ?) on conflict do update set vote = ?",
id,
message_id,
vote,
vote,
)
.execute(&state.db)
.await