Now I have moved from student halls to a house, I have begun playing more with media, for instance, I really like the idea of being able to easily play my music in the kitchen. The problem is, all my music is upstairs on my desktop computer, the solution? Mediatomb, Gnome and UPnP.
So what's UPnP, well, I don't really know, but what I have worked out so far, is it works across a network, UPnP devices can find each other automatically, and work out what each other can do.
For this experiment, I was interested in 3 classes of device in UPnP, controlers, media servers, and media renderers. Devices can be more than one class, for instance, lots of devices are media renderers and limited controllers, where the controller can only control the local device.
So, I began by installing mediatomb on my desktop machine. Mediatomb is a media server, it takes content, music pictures or video (and some other stuff), and makes it available over UPnP. Once installed you can configure it with the web interface at http://localhost:49152/ .
Next we need something to render the music that mediatomb makes available, so for this, I used Rygel. You might notice from the wiki page, that Rygel can also be a media server, I haven't tried this functionality as I prefer the daemon nature of mediatomb. So to use Rygel as a media renderer, the playbin plugin must be installed, in Debian this is as easy as installing the rygel-playbin package. Once done, run the rygel command, and if you see this message "Rygel-Message: New plugin 'Playbin' available", it hopefully means its working. I have Rygel currently running on an EeePC in my kitchen, although I am hoping to perhaps replace this with a raspberry pi in the future.
So lets recap, at the moment, my desktop machine is running mediatomb, sharing its content with the network, and my netbook is running Rygel, that can render content with the speakers connected to it. What we need next is a controller, to allow us to actually do something with this. For this we can use one of the gupnp tools, in Debian you need to install the gupnp-tools package. Then start the AV Controler, (gupnp-av-cp from the shell). This allows you to get content from the server, and play it on the renderer.
What I really like about this setup, is that its really extensible. If I can find/write a UPnP controller for my Android phone, I will be able to control the music for my house from my phone. I also found something called rhythmpnp, its a media renderer plugin for Rhythmbox, I haven't managed to run it yet, but I am interested in seeing if it could also be extended to act as a controller?
Sunday, 26 August 2012
Saturday, 25 August 2012
GSoC Update 7: Final Evaluation Result
Firstly, I am glad to say that I have passed the evaluation. But that does not mean that my project is over, the Gnome Sudoku game is not yet something that I would call complete.
So, since my last update, I have been working on learning, and implementing in Vala some of the logic techniques that can be used to solve sudokus. The best resource I have found so far for this is Sudopedia. I plan to display opportunities to apply the technique in a help section, as well as highlighting the relevant cells on mouseover.
I also decided to change the way possibilities for a cell are displayed to the user. You can see this, and the previously described feature in the following screenshot.
I realise that the display for the techniques is not brilliant, I am still working out exactly how to display all the information. I am also working to add lots more techniques.
So, since my last update, I have been working on learning, and implementing in Vala some of the logic techniques that can be used to solve sudokus. The best resource I have found so far for this is Sudopedia. I plan to display opportunities to apply the technique in a help section, as well as highlighting the relevant cells on mouseover.
I also decided to change the way possibilities for a cell are displayed to the user. You can see this, and the previously described feature in the following screenshot.
I realise that the display for the techniques is not brilliant, I am still working out exactly how to display all the information. I am also working to add lots more techniques.
Sunday, 19 August 2012
GSoC Update 6: Progress and the Firm Deadline
Since my last update, I have been working on making the game more playable before the end of my official contributions to the project as part of the GSoC are over. I plan to continue contributing to the project after this, but I would like to be able to submit something usable to Google.
So I began by adding a new game screen, this screen will also allow access to the previously played (saved) games.
Deciding what cell to give when the user requests a hint was done already, but displaying this hint was not. So I implemented a simple mechanism (probably in a bad way), to make the cell flash red. This is also used to warn the user when a cell becomes unfillable (if they have this option enabled).
The undo and redo functionality also needed fixing, I think some of the refactoring I did with the model code broke it. I also added a clear button to the number picker that appears over the board when you click a square.
The final important thing to mention is the preloaded puzzles. The game now includes some puzzles such that the user does not have to generate some straight away, this is also useful at the moment with the generator not fully working.
I next hope to add support for saving the state of current games to disk as JSON, and a help section to identify and explain logic techniques to the user.
So I began by adding a new game screen, this screen will also allow access to the previously played (saved) games.
Start Screen |
The undo and redo functionality also needed fixing, I think some of the refactoring I did with the model code broke it. I also added a clear button to the number picker that appears over the board when you click a square.
The final important thing to mention is the preloaded puzzles. The game now includes some puzzles such that the user does not have to generate some straight away, this is also useful at the moment with the generator not fully working.
I next hope to add support for saving the state of current games to disk as JSON, and a help section to identify and explain logic techniques to the user.
Wednesday, 1 August 2012
GSoC Update 5: Solving and Rating Sudoku's
I have now finished off writing, and done some testing of the Vala solver and rater. The solver took quite a while to write, mostly because of my in inexperience with python, once the solver was finished, I started writing the rater. The rater works by watching the solver at work, and using some of its methods in "fake" mode, where they do not actually affect the state of the board.
I have also added some "methods with syntax support" to the SudokuBoard class. This has two improvements in my opinion. Firstly, it allows for statements like this:
Next, I will either, depending on the feedback from my mentor, either continue working on the Sudoku generation code (using the solver I have just written to help), or continue working on the interface, adding error highlighting and a start screen.
I have also added some "methods with syntax support" to the SudokuBoard class. This has two improvements in my opinion. Firstly, it allows for statements like this:
if (board.cells[l1, l2] == 0)
to be simply written like:
if (board[l1, l2] == 0)
Secondly, it allows sanity checking of the input, to make sure the board can only contain values that its is supposed to.Next, I will either, depending on the feedback from my mentor, either continue working on the Sudoku generation code (using the solver I have just written to help), or continue working on the interface, adding error highlighting and a start screen.
Sunday, 22 July 2012
GSoC Update 4: Solving Sudoku's
In my previous post, I discussed my work on generating Sudoku puzzles. I had planned to try and improve this, and did make some small improvements, for instance adding a check at the end using the existing solver code to check for a unique solution. However I am not sure if this is a very good method.
While looking for inspiration in the python code, I noticed that its generator used the functionality of the solver to help it generate puzzles with a unique solution. So I decided to port the python Sudoku solver and rater directly.
At first this was very hard, the data structures in the python code are quite complicated and it uses them in some quite complicated ways. This is exacerbated by pythons use of duck typing. However, once I had worked out how to run the python code from the interpreter, either by pasting in the bit I was interested in, or by just importing the file and executing whole functions, the process went much quicker. I found that looking at the data structure, then working backwards to determine its function, then working out how to replicate that, was far quicker and easier than trying to reproduce the semantics of the code exactly.
I now have written out most of the solver, and understand some of it. The code currently on github will work for simple puzzles, but I am having problems determining if the guessing and backtracking part of the solver is correct. This is because when I run the python code, I believe the slight difference in implementation or the hashing function used in the sets in this part, causes their contents to be written out in a different order when converted to an array. This in turn, causes the two solvers to pick different paths, meaning that I can't directly compare the output.
Once this issue is solved, I should be able to calculate difficulty ratings for the Sudoku's. My current plan for solving it, devised while writing this blog post, is to add a function to both solvers, to sort the arrays that differ in such a way that they don't, then compare the resulting output of the solver.
Once I have done that, I will go through the code, adding plenty of comments to explain the methodology of the solver (this is once I have worked it out for myself!).
While looking for inspiration in the python code, I noticed that its generator used the functionality of the solver to help it generate puzzles with a unique solution. So I decided to port the python Sudoku solver and rater directly.
At first this was very hard, the data structures in the python code are quite complicated and it uses them in some quite complicated ways. This is exacerbated by pythons use of duck typing. However, once I had worked out how to run the python code from the interpreter, either by pasting in the bit I was interested in, or by just importing the file and executing whole functions, the process went much quicker. I found that looking at the data structure, then working backwards to determine its function, then working out how to replicate that, was far quicker and easier than trying to reproduce the semantics of the code exactly.
I now have written out most of the solver, and understand some of it. The code currently on github will work for simple puzzles, but I am having problems determining if the guessing and backtracking part of the solver is correct. This is because when I run the python code, I believe the slight difference in implementation or the hashing function used in the sets in this part, causes their contents to be written out in a different order when converted to an array. This in turn, causes the two solvers to pick different paths, meaning that I can't directly compare the output.
Once this issue is solved, I should be able to calculate difficulty ratings for the Sudoku's. My current plan for solving it, devised while writing this blog post, is to add a function to both solvers, to sort the arrays that differ in such a way that they don't, then compare the resulting output of the solver.
Once I have done that, I will go through the code, adding plenty of comments to explain the methodology of the solver (this is once I have worked it out for myself!).
Monday, 2 July 2012
GSoC Update 3: Sudoku Generation
I have been quite busy since my last report, both with GSoC stuff, and with moving house. I have now begun working on generating Sudoku puzzles, up until now, the sudoku-vala branch has had a hardcoded sudoku. The existing code is also much less in this area, compared with the functional interface, this was the extent of the generator:
The python code uses sets of coordinates, this made it slightly harder to translate as Vala can replicate some of this behaviour but its syntactically more expensive. So I chose to try and understand the methodology behind the code, and write in a style I believe more suits Vala.
The other missing bit from the Vala code concerning Sudoku generation was the solver, the current Vala solver doesn't have any publicly accessible methods for doing solving, it can only give tell you if the puzzle has 0, 1 or more than 1 solution. However it does this with a recursive (calls itself) method. I adapted this by introducing some random number generation, and placed it in the generator class to generate the full boards.
This is the second and slightly more complicated of the methods in the python code to produce Sudoku's. It generates puzzles that have a certain clue skew (unevenness).
This works by picking a number of cells from each box (the large 3 by 3 areas), then picking that many cells from within each box.
The python generation code generates puzzles, then using its quite complicated solver, solves them to generate some numbers (about 5) regarding the steps it took to solve them. These are then used to generate its difficulty score.
I am hoping that by tweaking the skew in the second method I describe, I hope that it will affect the difficulty of the resulting Sudoku. But I wont be able to evaluate this until I implement the solver.
public static SudokuGame generate (string difficulty)
{
var x = "";
for (var row = 0; row < 9; row++)
{
for (var col = 0; col < 9; col++)
{
var z = Random.int_range (0, 27);
if (z < 9)
x += "%d".printf (z);
else
x += ".";
}
}
return new SudokuGame.from_string (x);
}
So, I began with the python code, working out how it worked, and then replicating that in Vala. To my current understanding, the current Gnome Sudoku game first creates a complete board (with all the cells filled in), and then selects cells to be part of the puzzle. It can do the cell selection in different ways, the two ways I have currently looked at and replicated are make_puzzle_by_boxes, and make_symmetric_puzzle.The python code uses sets of coordinates, this made it slightly harder to translate as Vala can replicate some of this behaviour but its syntactically more expensive. So I chose to try and understand the methodology behind the code, and write in a style I believe more suits Vala.
The other missing bit from the Vala code concerning Sudoku generation was the solver, the current Vala solver doesn't have any publicly accessible methods for doing solving, it can only give tell you if the puzzle has 0, 1 or more than 1 solution. However it does this with a recursive (calls itself) method. I adapted this by introducing some random number generation, and placed it in the generator class to generate the full boards.
Making Symmetrical Sudoku's
I was a bit confused by the methodology in the python code, it seemed to involve two loops, whereas I chose to implement it using only one. My code, generates a filled and blank board. Then picks a cell on the grid randomly, checks if its been filled yet, and if not inserts the corresponding value in filled grid, then it works out the coordinate of the reflection in the bottom left to top right diagonal, and does the same. It then repeats the steps in the previous sentence until the new board (that began blank) has enough filled cells.Sudoku generated using the symmetrical method described above. |
Making Sudoku's by Box
This is the second and slightly more complicated of the methods in the python code to produce Sudoku's. It generates puzzles that have a certain clue skew (unevenness).
Skew of 0 |
Skew of 0.5 |
Skew of 1 |
Next
At the moment I have done some work on unifying the above methods, I aim to finish that off soon. I also would like to be able to produce symmetrical Sudoku's with different lines of symmetry (the code is limited to one in particular at the moment).The python generation code generates puzzles, then using its quite complicated solver, solves them to generate some numbers (about 5) regarding the steps it took to solve them. These are then used to generate its difficulty score.
I am hoping that by tweaking the skew in the second method I describe, I hope that it will affect the difficulty of the resulting Sudoku. But I wont be able to evaluate this until I implement the solver.
Thursday, 14 June 2012
GSoC Update 2: Implementing the New UI
So, I have been working on implementing the new UI. I worked out how Gtk layouts and packing work, and added a hint and back button to the control area (to the right of the grid).
Now, the number picker (the dialog that pops up when you double click a square), was created dynamically in one method. What I did is separate out the number picker in to a new Widget (I think this is the correct term?), called, wait for it, NumberPicker. This can be used in the dialog, for the double click functionality, but is also equally suited for use in the control area to the side.
I also while doing the above task, removed the deprecated Gtk.VBox, and Gtk.Table in the code, and replacing them with Gtk.Box, and Gtk.Grid respectively. I have spotted Table being used elsewhere, so I will probably try to go round and update all of these issues at some point.
Replacing the number picker in the SudokuCellView class (the bit that manages each individual cell on the grid) was relatively easy, once I (helped by my mentor) got an understanding of how to use signals. This was because I got the code I used for the NumberPicker from there.
The control section one was slightly harder as it is completely separate from the grid. I added event signals to the SudokuCellView class and SudokuView class (that handles the entire grid), such that I can get notified when a cell gains and loses focus. I then connected the gain focus event to a function that enabled or disabled the NumberPicker depending on whether the cell was editable. Then, as the cell loses focus when a button on the NumberPicker is pressed, I had to work out a way for the selected cell in the grid, to stay selected while the user was pressing buttons on the NumberPicker. So, as the current "selected" system used the focus property, I added a selected property to the SudokuCellView class, and then added selected_x, and selected_y properties to the SudokuView class.
Focus now just changes the selected cell on the grid, losing the focus from a cell, does not make it unselected. This allowed me to connect the number_picked signal from the NumberPicker to call a method I added to the SudokuView class to change the value in a given cell, using the selected_x and selected_y properties of the SudokuView to tell which cell is selected.
The end result of this work is demoed in the following video.
Next, I think I need to talk to both my mentor, and Allan Day, regarding the exact desired implementation of the UI. What I have works, however I have not thought much about how it looks yet.
Now, the number picker (the dialog that pops up when you double click a square), was created dynamically in one method. What I did is separate out the number picker in to a new Widget (I think this is the correct term?), called, wait for it, NumberPicker. This can be used in the dialog, for the double click functionality, but is also equally suited for use in the control area to the side.
I also while doing the above task, removed the deprecated Gtk.VBox, and Gtk.Table in the code, and replacing them with Gtk.Box, and Gtk.Grid respectively. I have spotted Table being used elsewhere, so I will probably try to go round and update all of these issues at some point.
Replacing the number picker in the SudokuCellView class (the bit that manages each individual cell on the grid) was relatively easy, once I (helped by my mentor) got an understanding of how to use signals. This was because I got the code I used for the NumberPicker from there.
The control section one was slightly harder as it is completely separate from the grid. I added event signals to the SudokuCellView class and SudokuView class (that handles the entire grid), such that I can get notified when a cell gains and loses focus. I then connected the gain focus event to a function that enabled or disabled the NumberPicker depending on whether the cell was editable. Then, as the cell loses focus when a button on the NumberPicker is pressed, I had to work out a way for the selected cell in the grid, to stay selected while the user was pressing buttons on the NumberPicker. So, as the current "selected" system used the focus property, I added a selected property to the SudokuCellView class, and then added selected_x, and selected_y properties to the SudokuView class.
Focus now just changes the selected cell on the grid, losing the focus from a cell, does not make it unselected. This allowed me to connect the number_picked signal from the NumberPicker to call a method I added to the SudokuView class to change the value in a given cell, using the selected_x and selected_y properties of the SudokuView to tell which cell is selected.
The end result of this work is demoed in the following video.
Next, I think I need to talk to both my mentor, and Allan Day, regarding the exact desired implementation of the UI. What I have works, however I have not thought much about how it looks yet.
Saturday, 2 June 2012
GSoC Update 1: New Sudoku UI
I began working today on writing the new UI (User Interface) for the Gnome Sudoku game, it follows the design set out here. It includes updating the applications menu to use the new style (using GMenu), and providing an interface that is more suitable to touch screen devices.
I was unable to work during the last few weeks because of University exams, now they are now finished. However I did do some work, submitting some small patches before the start of the coding period that:
Depending on the feedback from my mentor, I will probably continue updating the UI, this is somewhat matching my proposal, but instead of the number picker popup, there is now a separate entry location to the top right.
I was unable to work during the last few weeks because of University exams, now they are now finished. However I did do some work, submitting some small patches before the start of the coding period that:
- Changed the Gtk.Window, to Gtk.ApplicationWindow
- Changed the application to extend Gtk.Application
- Moved the main method to a separate file
Depending on the feedback from my mentor, I will probably continue updating the UI, this is somewhat matching my proposal, but instead of the number picker popup, there is now a separate entry location to the top right.
Tuesday, 24 April 2012
Google Summer of Code
I have been accepted in to the GSoC (Google Summer of Code), for my proposal to the Gnome project entitled Completion of the Gnome Sudoku Vala Port.
I am really excited about this, as it's a great opportunity to explore some of the new features introduced Gnome 3, and I hope I will be able to complete the core features of the Gnome Sudoku game, as well as some more advanced ones.
If you have any ideas/suggestions, please contact me.
I am really excited about this, as it's a great opportunity to explore some of the new features introduced Gnome 3, and I hope I will be able to complete the core features of the Gnome Sudoku game, as well as some more advanced ones.
If you have any ideas/suggestions, please contact me.
ORMLite and a Bundled Database
When writing one of my first Android apps, the Southampton Univeristy Map App (GitHub), using ORMLite to manage the database, I came across a few problems trying to include the database in assets. This I needed to do because creating the database on the device would require to much time and space.
To do this, I include my database in the assets folder (this I got from the emulator using the file explorer). I then included the following code at the start of the onCreate method of my launcher activity, this deals with incorrect versions of the database, by simply overriding it with the bundled version.
To do this, I include my database in the assets folder (this I got from the emulator using the file explorer). I then included the following code at the start of the onCreate method of my launcher activity, this deals with incorrect versions of the database, by simply overriding it with the bundled version.
try { File dbFile = new File(DATABASE_PATH + DATABASE_NAME); if (dbFile.exists()) { Log.i(TAG, "Database exists"); SQLiteDatabase checkDB = SQLiteDatabase.openDatabase(DATABASE_PATH + DATABASE_NAME, null, SQLiteDatabase.OPEN_READONLY); int version = checkDB.getVersion(); checkDB.close(); if (version != DATABASE_VERSION) { Log.i(TAG, "Not the right version"); copyDatabase(); } } else { Log.i(TAG, "Database does not exist"); SQLiteDatabase db = getHelper().getWritableDatabase(); if (USE_BUNDLED_DATABASE) { db.close(); copyDatabase(); } else { Log.i(TAG, "Creating database"); try { DataManager.createDatabase(instance); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } } catch (IOException e) { e.printStackTrace(); }Where DATABASE_PATH, DATABASE_NAME, DATABASE_VERSION are in an interface, implemented in both the database helper, and the launcher activity.
static final String DATABASE_PATH = "/data/data/net.cbaines.suma/databases/"; static final String DATABASE_NAME = "data.db"; static final int DATABASE_VERSION = 43;The copyDatabase method is also quite simple.
private void copyDatabase() throws IOException { Log.i(TAG, "Begining copy database"); InputStream myInput = getAssets().open(DATABASE_NAME); // Path to the just created empty db String outFileName = DATABASE_PATH + DATABASE_NAME; File database = new File(outFileName); if (database.exists()) { database.delete(); } // Open the empty db as the output stream OutputStream myOutput = new FileOutputStream(outFileName); // transfer bytes from the inputfile to the outputfile byte[] buffer = new byte[1024]; int length; while ((length = myInput.read(buffer)) > 0) { myOutput.write(buffer, 0, length); } // Close the streams myOutput.flush(); myOutput.close(); myInput.close(); Log.i(TAG, "Finished copying db"); }
Subscribe to:
Posts (Atom)