Merge lp:~andrenasturas/synapse-project/rolldice-plugin into lp:synapse-project

Proposed by André Nasturas on 2017-11-29
Status: Needs review
Proposed branch: lp:~andrenasturas/synapse-project/rolldice-plugin
Merge into: lp:synapse-project
Diff against target: 192 lines (+166/-0)
3 files modified
src/plugins/Makefile.am (+1/-0)
src/plugins/rolldice-plugin.vala (+164/-0)
src/ui/synapse-main.vala (+1/-0)
To merge this branch: bzr merge lp:~andrenasturas/synapse-project/rolldice-plugin
Reviewer Review Type Date Requested Status
Synapse core team 2017-11-29 Pending
Review via email: mp+334442@code.launchpad.net

Description of the change

Plugin for Rolldice.

Adds a plugin for the command-line program rolldice, allowing the user to throw dices and see results in synapse as easily as the calculator plugin.
User only have to type a command in rolldice syntax like "6d10+5" and the result will be printed.
Supports multiple dices rolls by returning as many results as rolls requested by the user.

Should be answering any string supported by rolldice :

Pseudo regex : [Ax]?[B]?dC[*D]?[+|-E]?[sF]?
All parts between brackets are optional.

The command can be interpreted as : "Roll B C-sized dices, drop the lowest F, multiply the result by D and add or subtract E, and do it A times independently".
A, B, C, D, E and F are all numbers.

C can also be "%", which is here a shortcut for "100-sized dice".
C cannot be 0 or 1, as these are not supported as number of faces by rolldice, and lead to unexpected results (rolldice use a default 6-sized dice instead).

Usage example :

"d6" : return a random number between 1 and 6.
"3xd4" : return three results, each being a random number between 1 and 4.
"6d10s4" : return a random number between 2 and 20 with a non-normal distribution, as it will roll 6 dices and keep only the two highest scores (dropping the 4 lowest) before summing.
"d5*2" : return a random even number between 2 and 10.
"d6+6" : return a random number between 7 and 12.

To post a comment you must log in.
Michael Aquilina (michaelaquilina) wrote :

Andre, this project isnt really active right now (from what I can tell). For this reason I have a fork on github that has a few improvements https://github.com/MichaelAquilina/synapse-project. Could I suggest you also open a PR there so that we get something released?

Unmerged revisions

656. By André Nasturas <email address hidden> on 2017-11-28

Added support for multiple rolls with multiple results

655. By André Nasturas <email address hidden> on 2017-11-28

Merge from main

654. By André Nasturas <email address hidden> on 2016-10-11

Add Rolldice plugin

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/plugins/Makefile.am'
2--- src/plugins/Makefile.am 2016-04-01 05:58:51 +0000
3+++ src/plugins/Makefile.am 2017-11-29 11:04:07 +0000
4@@ -49,6 +49,7 @@
5 pastebin-plugin.vala \
6 pidgin-plugin.vala \
7 rhythmbox-plugin.vala \
8+ rolldice-plugin.vala \
9 selection-plugin.vala \
10 test-slow-plugin.vala \
11 xnoise-media-player-plugin.vala \
12
13=== added file 'src/plugins/rolldice-plugin.vala'
14--- src/plugins/rolldice-plugin.vala 1970-01-01 00:00:00 +0000
15+++ src/plugins/rolldice-plugin.vala 2017-11-29 11:04:07 +0000
16@@ -0,0 +1,164 @@
17+/*
18+ * Copyright (C) 2017 André Nasturas <andre.nasturas+synapse@delfosia.net>
19+ *
20+ * This program is free software; you can redistribute it and/or modify
21+ * it under the terms of the GNU General Public License as published by
22+ * the Free Software Foundation; either version 2 of the License, or
23+ * (at your option) any later version.
24+ *
25+ * This program is distributed in the hope that it will be useful,
26+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28+ * GNU General Public License for more details.
29+ *
30+ * You should have received a copy of the GNU General Public License
31+ * along with this program; if not, write to the Free Software
32+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. *
33+ */
34+
35+namespace Synapse
36+{
37+ public class RolldicePlugin : Object, Activatable, ItemProvider
38+ {
39+ public bool enabled { get; set; default = true; }
40+
41+ public void activate ()
42+ {
43+
44+ }
45+
46+ public void deactivate ()
47+ {
48+
49+ }
50+
51+ private class Result : TextMatch
52+ {
53+ public int default_relevancy { get; set; default = 0; }
54+
55+ public Result (string result, string match_string)
56+ {
57+ Object (
58+ title: "%s".printf (result),
59+ description: "%s : %s".printf (match_string, result),
60+ has_thumbnail: false,
61+ icon_name: "applications-boardgames"
62+ );
63+ }
64+
65+ public override string get_text ()
66+ {
67+ return title;
68+ }
69+ }
70+
71+ static void register_plugin ()
72+ {
73+ PluginRegistry.get_default ().register_plugin (
74+ typeof (RolldicePlugin),
75+ _("Rolldice"),
76+ _("Rolls virtual dice."),
77+ "applications-boardgames",
78+ register_plugin,
79+ Environment.find_program_in_path ("rolldice") != null,
80+ _("rolldice is not installed")
81+ );
82+ }
83+
84+ static construct
85+ {
86+ register_plugin ();
87+ }
88+
89+ private Regex regex;
90+
91+ construct
92+ {
93+ /*
94+ This regex is based on the regex provided by rolldice documentation.
95+ It should catch a string formed like 6x5d7*2+4s3, which will be interpreted as
96+ "Roll five seven-sized dices, drop the lowest three, multiply the result by 2 and add 4,
97+ and do it 6 times independently."
98+ Also added a specific modification to prevent the regex catching "d0" and "d1" substrings
99+ (zero-sized and one-sized dice) to prevent unexcepted results (as it is not supported by
100+ rolldice, it may throw 6-sized dices instead, which could be surprising when the user ask
101+ for one one-sized dice and could except a 1 as result.)
102+ */
103+
104+ try
105+ {
106+ regex = new Regex (
107+ "^([0-9]+x)?[0-9]*d(([2-9]|[1-9][0-9]+)|%)(\\*[0-9]+)?((\\+|\\-)[0-9]+)?(s[0-9]+)?$",
108+ RegexCompileFlags.OPTIMIZE);
109+ } catch (Error e) {
110+ critical ("Error creating regexp.");
111+ }
112+ }
113+
114+ public bool handles_query (Query query)
115+ {
116+ return (QueryFlags.ACTIONS in query.query_type);
117+ }
118+
119+ public async ResultSet? search (Query query) throws SearchError
120+ {
121+ string input = query.query_string.replace (" ", "");
122+ bool matched = regex.match (input);
123+ if (!matched && input.length > 1)
124+ {
125+ input = input[0 : input.length - 1];
126+ matched = regex.match (input);
127+ }
128+ if (matched)
129+ {
130+ Pid pid;
131+ int read_fd, write_fd;
132+ string[] argv = {"rolldice"};
133+ string? solution = null;
134+
135+ try
136+ {
137+ Process.spawn_async_with_pipes (null, argv, null,
138+ SpawnFlags.SEARCH_PATH,
139+ null, out pid, out write_fd, out read_fd);
140+ UnixInputStream read_stream = new UnixInputStream (read_fd, true);
141+ DataInputStream rolldice_output = new DataInputStream (read_stream);
142+
143+ UnixOutputStream write_stream = new UnixOutputStream (write_fd, true);
144+ DataOutputStream rolldice_input = new DataOutputStream (write_stream);
145+
146+ rolldice_input.put_string (input + "\n", query.cancellable);
147+ yield rolldice_input.close_async (Priority.DEFAULT, query.cancellable);
148+ solution = yield rolldice_output.read_line_async (Priority.DEFAULT_IDLE, query.cancellable);
149+ solution = yield rolldice_output.read_line_async (Priority.DEFAULT_IDLE, query.cancellable);
150+ /* As rolldice send the input on the standard output, we read it twice to get the result */
151+
152+ if (solution != null)
153+ {
154+ ResultSet results = new ResultSet ();
155+ string[] solutions = solution.split(" ");
156+
157+ for (int i = 0; i < solutions.length; i++)
158+ {
159+ string s = solutions[i];
160+ if (s.length > 0) // Prevent empty solutions due to the split with a final whitespace
161+ {
162+ Result result = new Result (s, query.query_string);
163+ results.add (result, MatchScore.AVERAGE+i); // Prevent ResultSet to be sorted
164+ }
165+ }
166+ query.check_cancellable ();
167+ return results;
168+ }
169+ }
170+ catch (Error err)
171+ {
172+ if (!query.is_cancelled ()) warning ("%s", err.message);
173+ }
174+ }
175+
176+ query.check_cancellable ();
177+ return null;
178+ }
179+ }
180+}
181
182=== modified file 'src/ui/synapse-main.vala'
183--- src/ui/synapse-main.vala 2016-04-01 05:58:51 +0000
184+++ src/ui/synapse-main.vala 2017-11-29 11:04:07 +0000
185@@ -177,6 +177,7 @@
186 typeof (PassPlugin),
187 typeof (ChatActions),
188 typeof (ZealPlugin),
189+ typeof (RolldicePlugin),
190 #if HAVE_ZEITGEIST
191 typeof (ZeitgeistPlugin),
192 typeof (ZeitgeistRelated),