Skip to content

Commit

Permalink
Updates cli options; removes sonic
Browse files Browse the repository at this point in the history
  • Loading branch information
cachance7 committed May 12, 2020
1 parent eb9fd77 commit aba63c5
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 144 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "fuzzy5e"
version = "0.1.6"
version = "0.2.0"
authors = ["Casey Chance <casey@chance.email>"]
edition = "2018"

Expand Down
13 changes: 5 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<!-- ABOUT THE PROJECT -->
## About The Project

As a DM I find myself constantly looking up spells and monster stat blocks while running the game. As a programmer, the terminal is my most concise at-a-glance space for text information. After years of struggling to juggle browser windows and tabs, I decided to build this as a sort of quick reference and HUD for my most commonly referenced information.
As a DM I find myself constantly looking up spells and monster stat blocks while running the game. As a programmer, the terminal is my most concise at-a-glance space for text information. After years of struggling to juggle browser windows and tabs, I decided to build this as a sort of quick reference and HUD for my most commonly referenced information.

NOTE: This is very much a **_work in progress_**.

Expand All @@ -55,29 +55,26 @@ _Tiling in tmux turns out to be exactly what I wanted._
* [Rust](https://www.rust-lang.org/) - this app is written in rust
* [tuikit](https://github.com/lotabout/tuikit) - leaned on this heavily for the terminal UI presentation
* [5e-database](https://github.com/bagelbits/5e-database) - SRD5 data is sourced from here
* [Sonic](https://github.com/valeriansaliou/sonic) - used to index the information for quick on-the-fly lookup
* [Docker](https://www.docker.com/) - for running the dependent services and redistributing


<!-- GETTING STARTED -->
## Getting Started

fuzzy5e is a terminal UI written in Rust, but it relies on several external services to function. The easiest way to get up and running is to use Docker and docker-compose.
fuzzy5e is a terminal UI written in Rust. It has been tested on Mac OSX Catalina and Linux. YMMV on Windows.

### Prerequisites

- [Install Docker & docker-compose](https://docs.docker.com/get-docker/)

[Rust >=1.40](https://www.rust-lang.org/tools/install) (if building from source)

### Installation

1. Clone the repo
```sh
git clone https://github.com/cachance7/fuzzy5e
```
2. Run the helper script. After pulling and building the containers there is a one-time indexing that will occur.
2. Build and run the executable
```sh
cd fuzzy5e && ./fuzzy5e
cd fuzzy5e && cargo run
```
3. Enjoy!

Expand Down
6 changes: 0 additions & 6 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
version: "3.3"
services:
sonic:
image: valeriansaliou/sonic:v1.2.3
ports:
- "1491:1491"
volumes:
- "./config.cfg:/etc/sonic.cfg"
db:
image: fuzzylombax/5e-srd-database
ports:
Expand Down
59 changes: 11 additions & 48 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ extern crate pretty_env_logger;
#[macro_use]
extern crate log;



mod client;
mod db;
mod index;
Expand All @@ -16,7 +14,6 @@ mod tantivy;

use std::fs::File;
use simplelog;
use client::{Client, ClientOptions, Mode};
use crate::tantivy::*;
use db::DB;
use model::*;
Expand All @@ -28,15 +25,14 @@ use tuikit::canvas;
use tuikit::prelude::*;
use std::fmt;
use std::str::FromStr;
use std::net::ToSocketAddrs;
use std::fmt::{Display,Formatter};
use std::sync::{
Arc, Mutex,
};

struct Config {
sonic_addr: String,
mongo_addr: String,
index_dir: String,
}

quick_error! {
Expand Down Expand Up @@ -66,8 +62,8 @@ struct Cli {
/// Optional command. If not provided, program will be run in REPL mode
action: Option<CliAction>,

#[structopt(short, long, default_value = "[::1]:1491", env = "SONIC_ADDR")]
sonic_addr: String,
#[structopt(short, long, default_value = "./index", env = "INDEX_DIR")]
index_dir: String,

#[structopt(short, long, default_value = "localhost:27017", env = "MONGO_ADDR")]
mongo_addr: String,
Expand All @@ -86,10 +82,10 @@ enum Action {
Resize,
}

fn update_matches(idx: impl index::Indexer, conn: &DB, query: &str, matches: Arc<Mutex<Vec<Box<Model>>>>) {
fn update_matches(idx: impl index::Indexer, query: &str, matches: Arc<Mutex<Vec<Box<Model>>>>) {
if let Ok(mut matches) = matches.lock() {
matches.clear();
matches.extend(Model::indexed_query(idx, conn, query).unwrap());
matches.extend(Model::indexed_query(idx, query).unwrap());
}
}

Expand Down Expand Up @@ -338,37 +334,16 @@ impl Screen5e {

fn do_query(config: Config, query: &str) -> std::result::Result<(), Box<dyn Error>> {
trace!("do_query");
let db = DB::connect(&config.mongo_addr).expect("failed to connect to mongodb");
let options = ClientOptions{ addr: config.sonic_addr.to_socket_addrs()?.next().unwrap(), ..ClientOptions::default()};
let mut idx = Client::connect(options).expect("failed to connect to sonic");
let results = Model::indexed_query(idx.clone(), &db, &query);
let idx = Tantivy::new(TantivyOptions{index_dir: config.index_dir, ..TantivyOptions::default()});
let results = Model::indexed_query(idx.clone(), &query);
println!("{:?}", results);
idx.disconnect()?;
Ok(())
}

fn do_reindex_sonic(config: Config) -> std::result::Result<(), Box<dyn Error>> {
trace!("do_query");
let db = DB::connect(&config.mongo_addr).expect("failed to connect to mongodb");
let options = ClientOptions {
addr: config.sonic_addr.to_socket_addrs()?.next().unwrap(),
mode: Mode::Ingest,
..ClientOptions::default()
};
let mut idx = Client::connect(options).expect("failed to connect to sonic");

Model::flush_all(idx.clone())?;
Model::index_all(idx.clone(), &db)?;

idx.disconnect()?;
Ok(())
}

fn do_reindex(config: Config) -> std::result::Result<(), Box<dyn Error>> {
trace!("do_query");
let db = DB::connect(&config.mongo_addr).expect("failed to connect to mongodb");

let idx = Tantivy::new(TantivyOptions{rebuild: true, ..TantivyOptions::default()});
let idx = Tantivy::new(TantivyOptions{rebuild: true, index_dir: config.index_dir, ..TantivyOptions::default()});

Model::index_all(idx.clone(), &db)?;

Expand Down Expand Up @@ -414,7 +389,6 @@ fn do_run(config: Config) -> std::result::Result<(), Box<dyn Error>> {
let q2 = Arc::clone(&query);

let matches = Arc::new(Mutex::new(Vec::new()));
// let m2 = Arc::clone(&matches);

// Term is thread-safe
let term = Arc::new(Term::new().unwrap());
Expand All @@ -426,9 +400,7 @@ fn do_run(config: Config) -> std::result::Result<(), Box<dyn Error>> {
// NOTE: Keep these connections inside the thread. For some reason starting
// these from the main thread and then moving them prevents tuikit from
// receiving WINCH signals :/
let db = DB::connect(&config.mongo_addr).expect("This should not fail");
let idx = Tantivy::new(TantivyOptions::default());
// let idx = Client::connect(ClientOptions{addr: config.sonic_addr.to_socket_addrs().unwrap().next().unwrap(), ..ClientOptions::default()}).expect("failed to connect to sonic");
let idx = Tantivy::new(TantivyOptions{index_dir: config.index_dir, ..TantivyOptions::default()});
let mut last = String::default();
loop {
let q = if let Ok(query) = query.lock() {
Expand All @@ -439,7 +411,7 @@ fn do_run(config: Config) -> std::result::Result<(), Box<dyn Error>> {

if q != last && !q.is_empty() {
debug!("query is different");
update_matches(idx.clone(), &db, &q, Arc::clone(&matches));
update_matches(idx.clone(), &q, Arc::clone(&matches));
last.clear();
last.push_str(&q);
if let Ok(sc2) = sc2.lock() {
Expand Down Expand Up @@ -550,15 +522,6 @@ fn do_run(config: Config) -> std::result::Result<(), Box<dyn Error>> {
}
}

/// Checks sonic to see if docs need to be indexed
fn indexing_required(idx: &Client, conn: &DB) -> bool {
if let Ok(res) = Model::indexed_query(idx.clone(), conn, "fire") {
res.is_empty()
} else {
true
}
}

fn main() -> std::result::Result<(), Box<dyn Error>> {
let level = if let Ok(level) = std::env::var("RUST_LOG") {
if let Ok(lf) = simplelog::LevelFilter::from_str(&level) {
Expand All @@ -572,8 +535,8 @@ fn main() -> std::result::Result<(), Box<dyn Error>> {
let cli = Cli::from_args();

let config = Config {
sonic_addr: cli.sonic_addr,
mongo_addr: cli.mongo_addr,
index_dir: cli.index_dir,
};


Expand Down
93 changes: 13 additions & 80 deletions src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,18 @@ pub trait ModelQuery {

/// Performs a query in the index and returns Items. Default implementation looks up ids in the
/// index and then queries a database for those ids.
fn indexed_query(s: impl Indexer, db: &DB, qs: &str) -> Result<Vec<Box<Self::Item>>> {
let ids = s.query_ids(&Self::Item::collection(), qs)?;

let oids: Vec<ObjectId> = ids
.iter()
.map(|sid| bson::oid::ObjectId::with_string(sid).unwrap())
.collect();

let query: Document = doc! {"_id": {"$in": oids}};

Self::find(db, query)
fn indexed_query(s: impl Indexer, qs: &str) -> Result<Vec<Box<Self::Item>>> {
unimplemented!("TODO: implement the single model query");
// let ids = s.query_ids(&Self::Item::collection(), qs)?;
//
// let oids: Vec<ObjectId> = ids
// .iter()
// .map(|sid| bson::oid::ObjectId::with_string(sid).unwrap())
// .collect();
//
// let query: Document = doc! {"_id": {"$in": oids}};
//
// Self::find(db, query)
}
}

Expand Down Expand Up @@ -495,7 +496,7 @@ impl ModelQuery for Model {
}

/// Implementation for Model enum. This performs a query across all types.
fn indexed_query(s: impl Indexer, db: &DB, qs: &str) -> Result<Vec<Box<Self::Item>>> {
fn indexed_query(s: impl Indexer, qs: &str) -> Result<Vec<Box<Self::Item>>> {
trace!("indexed query");
let docs = s.query(&Self::Item::collection(), qs)?;
debug!("got {} docs", docs.len());
Expand Down Expand Up @@ -526,74 +527,6 @@ impl ModelQuery for Model {
}
}

// BEGIN old implementation
// let sids: Vec<(&str, &str)> = ids
// .iter()
// .map(|r: &String| -> (&str, &str) {
// let s: Vec<&str> = r.split(':').collect();
// (s.get(0).unwrap(), s.get(1).unwrap())
// })
// .collect();

//FIXME This is a very stupid implementation
// let oids: Vec<ObjectId> = sids
// .iter()
// .map(|(_, sid)| bson::oid::ObjectId::with_string(sid).unwrap())
// .collect();
//
// let query: Document = doc! {"_id": {"$in": oids}};
//
// let mut mresults = std::collections::HashMap::new();
// let mut results: Vec<Model> = Vec::default();
//
// results.extend(
// Spell::find(db, query.clone())?
// .iter()
// .map(|m| Model::Spell(*m.clone())),
// );
// results.extend(
// Monster::find(db, query.clone())?
// .iter()
// .map(|m| Model::Monster(*m.clone())),
// );
// results.extend(
// Class::find(db, query.clone())?
// .iter()
// .map(|m| Model::Class(*m.clone())),
// );
// results.extend(
// Condition::find(db, query.clone())?
// .iter()
// .map(|m| Model::Condition(*m.clone())),
// );
// results.extend(
// MagicSchool::find(db, query.clone())?
// .iter()
// .map(|m| Model::MagicSchool(*m.clone())),
// );
// results.extend(
// Equipment::find(db, query.clone())?
// .iter()
// .map(|m| Model::Equipment(*m.clone())),
// );
// results.extend(
// Feature::find(db, query.clone())?
// .iter()
// .map(|m| Model::Feature(*m.clone())),
// );
//
// for r in results {
// mresults.insert(r.id(), r);
// }
//
// let mut ordered_results = Vec::new();
// for id in ids {
// if let Some(r) = mresults.get(&id) {
// ordered_results.push(Box::new(r.clone()));
// }
// }
// END old implementation

Ok(results)
}
}
Expand Down

0 comments on commit aba63c5

Please sign in to comment.