Friday, April 15, 2016

Acer R5 471T and Tumbleweed/Windows dual boot



First what you notice is that laptop is very slim design. Keyboard looks so thin, make you think they don't actually move while typing at all :) But when you start to type, it is really great! Screen is very glossy so even a smallest light reflection will make you move your head to proper angle. But it is great for indoor use.

After pushing power button, Windows has booted in couple of seconds. Great, everything works, even keyboard back-light and multi touch screen! And now let's install Linux along with installed Windows 10.

First install partition manager and resize 250GB parition to 150GB to make 100GB of unpartitioned space.

Next you want to make a USB installation stick. For OpenSUSE Tumbleweed you need to use ImageUSB.
Download Tumbleweed DVD ISO image from HERE.

Stick your flash drive with Tumbleweed installation to usb slot. Enter BIOS with F2 end enable Boot select with F12, or continue to Boot section and move USB Flash drive to first position.

After that installation will start. Because we have UEFI secure boot enabled it will ask us for confirmation to trust opensuse binaries for booting. After that installation will find unpartitioned space and suggest partition setup for root, home and swap paritions. Also it will set a boot mount point to EFI boot partition. This will install EFI binaries to proper place inside EFI boot parition.

After installation is finished it will reboot to windows again. It is because windows is overriding grub boot settings. To get around this open command prompt as administrator and execute:
bcdedit /set {bootmgr} path \EFI\opensuse\shim.efi

Finally grub menu! Tumbleweed has booted but WiFi is not showing any networks found, and it says WiFi not available.
$ sudo lspci
01:00.0 Network controller: Qualcomm Atheros QCA6174 802.11ac Wireless Network Adapter (rev 32)

There is problem in firmware for this WiFi card and it does not work with 4.5.x kernel.
Solution is to download Windows firmware binary and replace it with current linux version like so:

$ sudo cp /lib/firmware/ath10k/QCA6174/hw3.0/board.bin /lib/firmware/ath10k/QCA6174/hw3.0/board.bin.orig
$ sudo mv ~/Downloads/eeprom_ar6320_3p0_NFA364xp.bin /lib/firmware/ath10k/QCA6174/hw3.0/board.bin
$ sudo reboot

Finally fully operative dual boot!
Enjoy!

Wednesday, March 2, 2016

AngularJS Single Page App with Laravel API


Idea is to create Single Page App in AngularJS to demonstrate basics such as:

  • custom directives
  • routing capabilities using hashtag
  • controllers for particular routes
  • making HTTP requests and handling responses
  • CRUD operations on frontend and API calls to the backend
  • uploading a file/image
  • pagination and accordion Boostrap UI components

AngularJS SPA files:
  • resources/views/index.blade.php
  • public/js/module/module_spa.js
Complete code can be found HERE.

Step by step Laravel work log for backend, can be found HERE.

Thursday, February 18, 2016

PHP solutions for Codility lessons


Hi Codilitiers!

I want to share with you solutions for Codility lessons as result of my preparations for Codility test. If you are using PHP to go through Codility lessons and tasks, THIS COULD HELP.

PHP-Codility


Codility tasks have been solved using PHP as preparation for TopTal.
There could be multiple 100% solutions for particular task and 
there are separated partial solutions in ./partial folder which 
represents solutions before perfect score was hit.

Hope it helps!

Play Chrome Chess at work

As a practice in NodeJS/SocketIO I've made simple Chrome extension to play chess online with your friends. It is still in beta but I will continue with development and support as much as spare time allows it.


ChromeChess is simple PVP version of good old chess where game of chess is just click away. 

This extension acts as simple chess user interface inside small popup window.

So, basically you can continue your daily work inside Chrome while still playing chess. When opponent makes his move you will be notified so you can open chess board and make your move.

Hope you like it. Enjoy!

P.S. For developers that want to help with development you can find me HERE.

Saturday, December 26, 2015

Ready for freelancing?

I’ve been a professional software/web developer for more than a decade, and up until now I mostly worked as full time employee in several companies and one contracting project as freelancer, where I gained expertise in many technologies and Scrum Master management skills. Latest technologies were mostly web development oriented.

After a decade of my professional life I could say that full time corporate job is right choice if you don't have much experience or you just got out of school. After gaining initial experience in corporate jobs, you will want to make portfolio populated with projects you have worked on. You will need a portfolio to show to future clients that you are right choice for them. Experience proves both client and you that you are capable of finishing projects.

After that you could try yourself working by contract or as freelancer, having flexible working hours, where the end result counts. You need to have self-discipline to work when needed and be reliable and responsible while communicating to clients. This will also help you make time to stay sharp and in step with technology edge, because you are in control of your availability. All this is just what I always wanted so I decided that it is time to dive into freelance world.

In corporate culture, if you think in terms of financial part of software and its price, then of course you would like to finish it ASAP to reduce its cost. Companies driven by that notion only, will often threat its developers as necessary evil. For those companies, it is not the product that is in focus and value it brings to client, but rather the points of contracted work and its unreasonable deadlines.

Often under management pressure to follow deadlines, developers reduce products quality to gain speed. Not the career plan you would like to follow, because you don't have time to improve and work is not fun in such stressed environments.

Then I searched for freelance market sites. And I found sites like UpWork and Elance which are great but they don't guarantee you constant work because first you need to build your reputation and even than you have to compete with some very low unreasonable offers.

If only there could be some intermediate which will connect self-organizing teams of professionals with right customers, willing to pay for good quality product along with reasonable deadlines (so we don't need to compete with immoral offers to jobs like to make a copy of popular social network for 30$, or less, in couple of days). With financial aspect covered, team job is to handle time and quality aspect and gets job done. Team than incrementally develops software and brings value to customer so they together can steer product in right direction.

And then I heard of TopTal while attending presentation with freelancing as topic. It was scheduled at gathering of developer community of Banja Luka. Ines Avdic Zekic from Sarajevo held informative presentation about TopTal. Less than 3% passes screening process, she said. Nobody likes to be tested, but if this is what I have to pass to put financial aspect in background than by all means, let’s do this.

Why join TopTal?

If you pass TopTal screening process, then TopTal stands for you. TopTal takes care of finding jobs and paying you upon completed work, even in such cases where the customer refuses to pay. Take worries about not being paid away, and just commit yourself to finish your job.
Yours is to get job done. Money should be just a side effect of your work.
You can set higher or lower price per hour and frequency of jobs you receive will depend on that. Higher the price per hour, lower frequency of jobs.
It enables you to connect with other freelance professionals and do work together for TopTal trusted customers and companies.
You are not tied to location, as long as you have reliable internet connection.
Market is dictating new technologies, and that technology edge is exactly what you want to learn and contribute in. TopTal enables you to grow as IT professional. It provides you with courses and webinars to learn technologies with highest demand on market. 
It enables you to grow your software using edge technologies to bring better value to its users. You don’t wont to end up in companies just to maintain some piece of software until time and new technologies overrun them.
Availability and commitment can be changed. Your availability varies and you can reduce your availability while you are travelling or on vacation, and also increase it when you are eager to work.
Working 9-5 is not necessary what will bring the most out of developer. I want to use morning hours for work because I'm well rested. Then after lunch I could take a nap, do some physical activities and then go back to work and finish work refreshed and sharp minded.

In Banja Luka, there is still no developers working for TopTal. This would be a great opportunity to make a first step to connect TopTal with talented developers from this region and Banja Luka developer’s community. What I’ve heard so far, convinced me more that TopTal is right fit for me. I’m eager to learn new technologies and improve myself through active communication with TopTal clients and deliver them good piece of useful software. Later on my ambitions would be to gather people around me so we could provide TopTal services in a wide range of technologies as a self-organized team.

Now I'm heading back to Codility for some more practice. TopTal is also providing guide for interviewing PHP developers.

Wish me luck!

Tuesday, July 14, 2015

Simple blog using Laravel - Part I

Migrations

Create articles migration:
$ php artisan make:migration create_articles_table --create="articles"
Inside database/migrations find created migration and edit:
2015_07_13_192755_create_articles_table.php
and add these lines to up() method:
Schema::create('articles', function (Blueprint $table) {
    $table->increments('id');
    $table->string('title');
    $table->text('body');
    $table->text('excerpt')->nullable();
    $table->timestamp('published_at');
    $table->timestamps();
});
To execute created migration do:
$ php artisan migrate

Routes

Edit
app\Http\routes.php
and add this line:
Route::resource('articles', 'ArticlesController');
Which is easier way and equal to manually supply all CRUD routes following REST convention like so:
Route::get('articles', 'ArticlesController@index');
Route::get('articles/create', 'ArticlesController@create');
Route::get('articles/{id}', 'ArticlesController@show');
Route::post('articles', 'ArticlesController@store');
Route::get('articles/{id}/edit', 'ArticlesController@edit');

Model

We have articles table, so lets create Article model:
$ php artisan make:model Article
Edit our model app\Article.php and add $fillable fields so we can mass assign them while creating article. Also specify published_at field inside $dates so Laravel threat this field as Carbon date object instead of simple string representation.
class Article extends Model
{
    protected $dates = ['published_at'];
    protected $fillable = [
    'title',
    'body',
    'published_at'
    ];
}

Add two rows to article table using Laravel interactive tinker tool:
$ php artisan tinker;
$ App\Article::create(['title' => 'My first article', 'body' => 'Article body', 'published_at' => Carbon\Carbon::now()]);
$ App\Article::create(['title' => 'New article', 'body' => 'New body', 'published_at' => Carbon\Carbon::now()]);
$ App\Article::all();
Update first article:
$article = App\Article::find(1);
$article->body = 'Lorem ipsum';
$article->save();
App\Article::all();
Get collection of articles:
$articles = App\Article::where('body','Lorem ipsum')->get();
Get first article:
$article = App\Article::where('body','Lorem ipsum')->first();

Controller

Let's create plain ArticlesController:
$ php artisan make:controller ArticlesController --plain
So now we will create index action to fetch list of articles.
Edit app\Http\Controllers\ArticlesController.php:
public function index()
{
    $articles = Article::latest('published_at')->published()->get();
    return view('articles.index', compact('articles'));
}
We want to use published() scope while fetching articles to get only those published until today and sort them descending from newest to oldest by published_at using latest(). So let's create published() scope in app\Article.php model. Notation is keyword scope followed by scope name, like this:
use Carbon\Carbon;
public function scopePublished($query)
{
    $query->where('published_at', '<=', Carbon::now());
}
To show details of selected article we need show() action. Edit app\Http\Controllers\ArticlesController.php:
public function show($id)
{
    $article = Article::findOrFail($id);
    return view('articles.show', compact('article'));
}

View

Inside resources folder create app.blade.php:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">
@yield('content')
</div>
@yield('footer')
</body>
</html>
Inside resources\articles create index.blade.php:
@extends('app')
@section('content')
<div class="col-md-12 staff-header">
<h5>Articles</h5>
</div>
<div class="col-xs-12 col-md-12">
@foreach( $articles as $article)
<article>
<h4>
<a href="{{ action('ArticlesController@show', [$article->id]) }}">{{ $article->title }}</a>
</h4>
<h6>{{ $article->body }}</h6>
<br/>
</article>
@endforeach
</div>
@stop
Inside resources\articles create show.blade.php:
@extends('app')
@section('content')
<div class="col-md-12 staff-header">
<h5>{{ $article->title }}</h5>
</div>
<div class="col-xs-12 col-md-12">
<article>
<h6>{{ $article->body }}</h6>
</article>
</div>
@stop

Tuesday, June 30, 2015

Laravel on Debian Wheezy

LAMP

First we need LAMP packages installed.
Laravel requires PHP >= 5.5.9 so we will install php56.

Add package repositories to apt sources.
Edit sources.list
$ vi /etc/apt/sources.list
and add these two lines:
deb http://packages.dotdeb.org wheezy-php56 all
deb-src http://packages.dotdeb.org wheezy-php56 all

Add dotdeb.gpg key so apt can authenticate packages from added sources.
$ cd
$ wget http://www.dotdeb.org/dotdeb.gpg
$ apt-key add dotdeb.gpg
$ apt-get update

Install Apache, MySQL and PHP
$ apt-get install mysql-server mysql-client
$ apt-get install apache2
$ apt-get install php5 libapache2-mod-php5 php5-mcrypt

Enable rewrite apache modul
$ a2enmod rewrite
$ /etc/init.d/apache2 restart

Confirm that php is working well with apache by creating info.php file:
$ vi /var/www/info.php
add this line:
<?php phpinfo(); ?>
Access inside browser: http://localhost/info.php

Laravel

# To install laravel we need composer:
$ sudo curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

* Use composer to install laravel:
$ composer global require "laravel/installer=~1.1"

* Add laravel bin to your PATH so you can use laravel executable from any location. Edit bash_profile file:
$ vi ~/.bash_profile
and add these lines:
PATH=$PATH:~/.composer/vendor/bin
export PATH

* Create new base for web application
$ cd ~/NetBeansProjects
$ laravel new LaravelDemo

# Or we could skip installing laravel and using it's executable to create base for web application (steps marked with asterisk *), and go ahead do all that with composer directly:
$ rm -rf ~/NetBeansProjects/LaravelDemo
$ cd ~/NetBeansProjects
$ composer create-project laravel/laravel LaravelDemo --prefer-dist

# Create Apache VirtualHost by:
$ vi /etc/apache2/sites-available/laraveldemo.org
and add these lines:
ServerAdmin webmaster@laraveldemo.org
ServerName  laraveldemo.org
ServerAlias *.laraveldemo.org

DocumentRoot /home/{user}/NetBeansProjects/LaravelDemo/public

        Options Indexes FollowSymLinks MultiViews
        AllowOverride All
        Order allow,deny
        allow from all

ErrorLog ${APACHE_LOG_DIR}/laraveldemo_error.log

# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn

CustomLog ${APACHE_LOG_DIR}/laraveldemo_access.log combined

# Enable virtual host:
$ a2ensite laraveldemo.org

# Add virtual host to hosts file by editing:
$ vi /etc/hosts
add this line:
127.0.0.1 laraveldemo.org

# Restart apache
$ service apache2 restart

# Create simple /about route and appropriate controller, action and view
$ cd ~/NetBeansProjects/LaravelDemo
$ vi app/Http/routes.php 
add this line to routes.php:
Route::get('about', 'PagesController@about');

# Create PagesController by:
$ php artisan make:controller PagesController --plain
$ vi app/Http/Controllers/PagesController.php
 
add about() method to PagesController.php:
    public function about() {
    return view('about');
    }

# Create about view by editing about.blade.php:
$ vi resouces/views/about.blade.php
add this line:
    Hello World

# Make local configuration
$ copy .env.example to .env

# Generate app key
$ php artisan key:generate

# Set Directory Permissions
$ cd ~/NetBeansProjects/LaravelDemo
$ chgrp www-data -Rv storage/
$ chmod g+w -Rv storage/
$ cd bootstrap/
$ chgrp www-data -Rv cache
$ chmod g+w -Rv cache

Test it by pointing browser to:
http://laraveldemo.org/about

Create database
mysql> create database laraveldemo;
mysql> CREATE USER 'laraveldemouser'@'localhost' IDENTIFIED BY 'laraveldemopass';
mysql> GRANT ALL ON laraveldemo.* TO 'laraveldemouser'@'localhost';

# Add mysql authentication data to .env
$ vi .env
change these lines:
DB_HOST=localhost
DB_DATABASE=laraveldemo
DB_USERNAME=laraveldemouser
DB_PASSWORD=laraveldemopass

Monday, August 9, 2010

How to load/write XML using JAXB?

Every now and then you need to load or write some XML files. It is very effective way to put data in machine-readable form. XML is text format file which is well formatted using standardized rules.

So to demonstrate use of JAXB we will:
1) create XML file with some data (bookmarks.xml)
2) create XML schema file to validate our XML file (bookmarks.xsd)
3) create XML object model using xjc utility (xjc.txt)
4) load that XML file into JAXB object (XMLUnmarshall.java)
5) write JAXB object back over original XML file (XMLMarshaller.java)
6) create main java class to call these functions in appropriate order (JAXBLoader,java)

Create XML file
Lets create a simple xml file for storing bookmark data organized through sets. It will contain root element bookmarks with bookmark elements inside and list of attribute elements for storing href values. Also for every bookmark element there will be a attribute set which will identify current bookmark set. Example of this xml can be found here: bookmarks.xml.

Create XML schema file
To validate bookmark.xml we need to create schema file. Example for this example can be found here: bookmarks.xsd.

Create object model
To create object model for our xml we need to run xjc utility and supply it with xsd schema file as argument at command line.

zlaja@orion:~/NetBeansProjects/JAXBLoader> xjc ./data/bookmarks.xsd -p com.blogspot.zetaorionis.bookmarks.model -d ./src
parsing a schema...
compiling a schema...
com/blogspot/zetaorionis/bookmarks/model/AttributeType.java
com/blogspot/zetaorionis/bookmarks/model/Bookmark.java
com/blogspot/zetaorionis/bookmarks/model/Bookmarks.java
com/blogspot/zetaorionis/bookmarks/model/ObjectFactory.java
com/blogspot/zetaorionis/bookmarks/model/package-info.java
zlaja@orion:~/NetBeansProjects/JAXBLoader>

Unmarshalling / loading XML data to object model instance
This utility class will help you read xml file into it's object representation. It will work with every xml file. You just need to supply it with uri path to xml file:
data/bookmarks.xml

and root element class of object model:
Bookmarks.class

Here is XMLUnmarshaller.java utility class:

package com.blogspot.zetaorionis.util.xml;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;
import java.net.URI;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import org.apache.log4j.Logger;

/**
*
* @author zlaja
*/
public class XMLUnmarshaller {

private static final Logger logger = Logger.getLogger(XMLUnmarshaller.class);
/**
* The bookmark file.
*/
protected URI uri;

/**
* Create an xml based loader of bookmarks.
* @param uri the bookmark file
*/
public XMLUnmarshaller(final URI uri) {
this.uri = uri;
}

//
// BookmarksXMLLoader
//
/**
* Load bookmarks into a action list.
*
* @throws IOException
* If an I/O error occurred.
* @throws FileNotFoundException
* If the resource was not found.
*/
public T load(Class docClass) throws IOException {
final InputStream in = getClass().getResourceAsStream("/" + uri.getPath());

if (in == null) {
throw new FileNotFoundException("Cannot find resource: " + uri);
}

try {
return load(docClass, in);
} finally {
in.close();
}
}

protected T load(Class docClass, final InputStream in) {
T o = null;
try {
o = unmarshal(docClass, in);
} catch (JAXBException ex) {
logger.error("Error while unmarshalling.", ex);
}
return o;
}

public T unmarshal(Class docClass, InputStream inputStream)
throws JAXBException {
String packageName = docClass.getPackage().getName();
JAXBContext jc = JAXBContext.newInstance(packageName);
Unmarshaller u = jc.createUnmarshaller();
JAXBElement doc = u.unmarshal(new StreamSource(inputStream), docClass);
return doc.getValue();
}
}

Marshalling / writing data to xml from object model instance
This utility class will help you write data from object representation to xml file. It will work with every xml file. You just need to supply it with uri path to xml file:
data/bookmarks.xml

and root element class of object model:
Bookmarks.class

Here is XMLMarshaller.java utility class:
package com.blogspot.zetaorionis.util.xml;

import java.io.FileNotFoundException;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.net.URI;
import java.io.IOException;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.apache.log4j.Logger;

/**
*
* @author zlaja
*/
public class XMLMarshaller {

private static final Logger logger = Logger.getLogger(XMLUnmarshaller.class);
/**
* The output XML file.
*/
protected URI uri;

/**
* Create an xml based writer for specified jaxbObject.
* @param uri - uri for output XML file
*/
public XMLMarshaller(final URI uri) {
this.uri = uri;
}

//
// XMLMarshaller
//
/**
* Write JAXBElement representation of object to XML file.
*
* @param jaxbObject - object for marshalling to xml, converted to JAXBElement.
* Conversion is done using function inside ObjectFactory.java which is
* created with xjc utility
* @param docClass - class for object that is going to be marshalled to XML
*
* @throws IOException
* If an I/O error occurred.
* @throws FileNotFoundException
* If the resource was not found.
*/
public void write(final JAXBElement jaxbObject, Class docClass) throws IOException {
final OutputStream os = new FileOutputStream(uri.getPath());

if (os == null) {
throw new FileNotFoundException("Cannot create resource: " + uri);
}

try {
write(jaxbObject, docClass, os);
} finally {
os.close();
}
}

protected void write(final JAXBElement jaxbObject, Class docClass, final OutputStream os) {
try {
marshall(jaxbObject, docClass, os);
} catch (JAXBException ex) {
logger.error("Error in marshalling to XML.", ex);
}
}

private void marshall(final JAXBElement jaxbObject, Class docClass, final OutputStream os)
throws JAXBException {
String packageName = docClass.getPackage().getName();
JAXBContext context = JAXBContext.newInstance(packageName);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(jaxbObject, os);
}
}

Call utility classes inside main class
package com.blogspot.zetaorionis.jaxbloader;

import com.blogspot.zetaorionis.bookmarks.model.Bookmarks;
import com.blogspot.zetaorionis.bookmarks.model.ObjectFactory;
import com.blogspot.zetaorionis.util.xml.XMLMarshaller;
import com.blogspot.zetaorionis.util.xml.XMLUnmarshaller;
import java.net.URI;
import org.apache.log4j.Logger;

/**
*
* @author zlaja
*/
public class JAXBLoader {

private static final String LOG4J_PROPERTIES = "data/log4j.properties";
private static final Logger logger = Logger.getLogger(JAXBLoader.class);
private Bookmarks bookmarks = new Bookmarks();

public JAXBLoader() {
Log4J.init(LOG4J_PROPERTIES);
}

/**
* Loads XML data to object
*/
private void loadBookmarks() {
try {
final String path = "data/bookmarks.xml";
final URI uri = new URI(path);

final XMLUnmarshaller xmlBookmarks = new XMLUnmarshaller(uri);
this.bookmarks = xmlBookmarks.load(Bookmarks.class);
logger.info("Info: Bookmarks loaded successfuly.");
} catch (Exception ex) {
logger.error("Error: Loading bookmarks XML file failed", ex);
}
}

/**
* Writes object data to XML
*/
private void writeBookmarks() {
try {
final String path = "data/bookmarks.xml";
final URI uri = new URI(path);

final XMLMarshaller xmlBookmarks = new XMLMarshaller(uri);
ObjectFactory of = new ObjectFactory();
xmlBookmarks.write(of.createBookmarks(this.bookmarks), Bookmarks.class);
logger.info("Info: Bookmarks written successfuly.");
} catch (Exception ex) {
logger.error("Error: Writing bookmarks XML file failed", ex);
}
}

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
JAXBLoader loader = new JAXBLoader();
loader.loadBookmarks();
loader.writeBookmarks();
}
}