First encounter with React JS

This is a small demo made using React and Boostrap. It’s a list page which contains some of the Avengers, with the possibility to access a show page with details for each character.

This is a small demo made using React and Boostrap. It’s a list page which contains some of the Avengers, with the possibility to reach a show page with details for each character.

The purpose of the demo was to get an opinion on this JavaScript library for user interfaces, since I’m not a big fan of frontend development.

The conclusion:

  • Suitable for simple interfaces;
  • Easy to learn;
  • Possibility  to port the web application to a native iOS or Android application with minimum of effort, using React Native.

The demo: http://cristian-radulescu.ro/github-demos/react_demo-avengers/index.html.

The code: https://github.com/cristianradulescu/react_demo-avengers.

Screenshots:

react_demo_avengers_list_page react_demo_avengers_show_page

Add PDF export functionality in SonataAdminBundle

By default SonataAdminBundle doesn’t come with a PDF export functionality. Since this is a nice feature to have in your application here’s a way to add PDF export to the CRUD pages. The example works with the standard Symfony2 installation and the AcmeDemoBundle. The PDF will be generated using KnpSnappyBundle.

By default SonataAdminBundle doesn’t come with a PDF export functionality. Since this is a nice feature to have in your application here’s a way to add PDF export to the CRUD pages.

The example works with the standard Symfony2 installation and the AcmeDemoBundle. The PDF will be generated using KnpSnappyBundle (the installation process is not covered here).

The Doctrine Entity:

See http://cristian-radulescu.ro/article/doctrine-entities-in-twig-templates.html

The Color Admin class:

// src/Acme/DemoBundle/Admin/ColorAdmin.php

namespace Acme\DemoBundle\Admin;

use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Validator\ErrorElement;
use Sonata\AdminBundle\Form\FormMapper;

class ColorAdmin extends Admin
{
    public $baseRouteName = 'color';
    public $baseRoutePattern = '/color';

    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
            ->add('name')
            ->add('hex');
    }

    protected function configureDatagridFilters(DatagridMapper $datagridMapper)
    {
        $datagridMapper
            ->add('name')
            ->add('hex');
    }

    protected function configureListFields(ListMapper $listMapper)
    {
        $listMapper
            ->addIdentifier('name')
            ->add('hex');
    }
}

Enable the PDF export link on list page

In order to add the PDF export option the “getExportFormats” method needs to be overridden in the ColorAdmin class:

public function getExportFormats()
{
    return array_merge(parent::getExportFormats(), array('pdf'));
}

The “pdf” options should now be displayed on the list page next to the default ones.

Create custom service to handle PDF export

First the default export service (identified by “sonata.admin.exporter”) needs to be overriden. Register the service in src/Acme/DemoBundle/Resources/config/services.xml and make it aware of the knpSnappyPdf. Also the template engine will be necessary.

<service id="sonata.admin.exporter" class="Acme\DemoBundle\Export\Exporter">
    <call method="setKnpSnappyPdf">
        <argument type="service" id="knp.snappy_pdf" />
    </call>
    <call method="setTemplateEngine">
        <argument type="service" id="templating" />
    </call>
</service>

Next extend the Sonata exporter class as defined in the overridden exporter service:

// src/Acme/DemoBundle/Export/Exporter.php

namespace Acme\DemoBundle\Export;

use Exporter\Source\SourceIteratorInterface;
use Symfony\Component\HttpFoundation\Response;
use Sonata\AdminBundle\Export\Exporter as BaseExporter;

class Exporter extends BaseExporter
{
    protected $knpSnappyPdf;
    protected $templateEngine;

    public function getResponse($format, $filename, SourceIteratorInterface $source)
    {
        if ('pdf' != $format) {
            return parent::getResponse($format, $filename, $source);
        }

        $html = $this->templateEngine->renderView('AcmeDemoBundle:Export:pdf.html.twig', array(
            'source' => $source
        ));
        $content = $this->knpSnappyPdf->getOutputFromHtml($html);

        return new Response($content, 200, array(
            'Content-Type' => 'application/pdf',
            'Content-Disposition' => sprintf('attachment; filename=%s', $filename)
        ));
    }

    public function setKnpSnappyPdf($service)
    {
        $this->knpSnappyPdf = $service;
    }

    public function setTemplateEngine($service)
    {
        $this->templateEngine = $service;
    }
}

The last step is to add the Twig template used to render the PDF content, as specified in the custom exporter service.  For example:

{# src/Acme/DemoBundle/Resources/views/Export/pdf.html.pdf #}

<table border="1">
    <tr>
        <th>ID</th>
        <th>Name</th>
        <th>HEX</th>
    </tr>
    {% for elements in source %}
        <tr>
        {% for element in elements %}
            <td>{{ element }}</td>
        {% &nbsp;endfor %}
        </tr>
    {% endfor %}
</table>

Of course, there is room for improvement. You can do it “SonataAdmin” way with a custom PdfWriter class (similar with the built-in XlsWriter, CsvWriter or JsonWriter) to separate the PDF conversion code, instead of having the entire process in the custom Exporter class.

Beautiful strings and the PHP solution

“Beautiful strings” is one of the proposed problems on Facebook Hacker Cup 2013 Qualification Round. The presented PHP solution was already validated.

“Beautiful strings” is one of the proposed problems on Facebook Hacker Cup 2013 Qualification Round. The presented PHP solution was already validated.

The problem:

When John was a little kid he didn’t have much to do. There was no internet, no Facebook, and no programs to hack on. So he did the only thing he could… he evaluated the beauty of strings in a quest to discover the most beautiful string in the world.

Given a string s, little Johnny defined the beauty of the string as the sum of the beauty of the letters in it.

The beauty of each letter is an integer between 1 and 26, inclusive, and no two letters have the same beauty. Johnny doesn’t care about whether letters are uppercase or lowercase, so that doesn’t affect the beauty of a letter. (Uppercase ‘F’ is exactly as beautiful as lowercase ‘f’, for example.)

You’re a student writing a report on the youth of this famous hacker. You found the string that Johnny considered most beautiful. What is the maximum possible beauty of this string?

Input
The input file consists of a single integer m followed by m lines.

Output
Your output should consist of, for each test case, a line containing the string “Case #x: y” where x is the case number (with 1 being the first case in the input file, 2 being the second, etc.) and y is the maximum beauty for that test case.

Constraints
5 ≤ m ≤ 50
2 ≤ length of s ≤ 500

Example input:

5
ABbCcc
Good luck in the Facebook Hacker Cup this year!
Ignore punctuation, please 🙂
Sometimes test cases are hard to make up.
So I just go consult Professor Dalves

Example output:

Case #1: 152
Case #2: 754
Case #3: 491
Case #4: 729
Case #5: 646

The PHP solution:

$filename = 'input.txt';
$file = fopen($filename, 'r');
$contents = fread($file, filesize($filename));
$strings = explode(PHP_EOL, trim($contents));

// remove strings count
unset($strings[0]);

foreach ($strings as $case => $string) {
  calculate_beauty($string, $case);
}

function calculate_beauty($string, $case)
{
  $string = strtolower($string);
  $arr = array();
  for ($i = 0; $i < strlen($string); $i++) {
    if (ctype_alpha($string[$i])) {
      $arr[$string[$i]] = isset($arr[$string[$i]]) ? $arr[$string[$i]] + 1 : 1;
    }
  }

  rsort($arr);
  $beauty = 0;
  $letter_range = range(26, 1);

  for ($i = 0; $i < count($arr); $i++) {
    $beauty += $arr[$i] * $letter_range[$i];
  }

  echo 'Case #'.$case.': '.$beauty.'<br>';
}

More details about the solutions on the official page Qualification Round Solutions.

Doctrine entities in Twig templates

In a Symfony2 project, Doctrine entities can be used inside Twig templates with the help of Twig extensions.
The example works with the standard Symfony2 installation and the AcmeDemoBundle.

In a Symfony2 project, Doctrine entities can be used inside Twig templates with the help of Twig extensions.

The example works with the standard Symfony2 installation and the AcmeDemoBundle, and it is supposed to add a set of links on one of the demo pages. Each link represents a color, while the HEX code for that color is displayed when the link is clicked. The colors are retrieved from the database.

The example is using Twig functions, but an alternative which is using global variables is also presented.

The Doctrine entity:

// src/Acme/DemoBundle/Entity/Color.php

namespace Acme\DemoBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="color")
 */
class Color
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=100)
     */
    protected $name;

    /**
     * @ORM\Column(type="string", length=8)
     */
    protected $hex;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set name
     *
     * @param string $name
     * @return Color
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set hex
     *
     * @param string $hex
     * @return Color
     */
    public function setHex($hex)
    {
        $this->hex = $hex;

        return $this;
    }

    /**
     * Get hex
     *
     * @return string
     */
    public function getHex()
    {
        return $this->hex;
    }
}

This entity has a basic structure which should store the name and HEX code for a color.

The Twig extension:

// src/Acme/DemoBundle/Twig/Extension/ColorExtension.php

namespace Acme\DemoBundle\Twig\Extension;

/**
 * Custom Twig extension used to retrieve the colors.
 */
class ColorExtension extends \Twig_Extension
{
    /**
     * @var EntityManager
     */
    protected $em;

    public function __construct($em)
    {
        $this->em = $em;
    }

    public function getName()
    {
        return 'color_extension';
    }

    public function getFunctions()
    {
        return array(
            'get_colors' => new \Twig_Function_Method($this, 'getColors')
        );
    }

    public function getColors()
    {
        return $this->em->getRepository('AcmeDemoBundle:Color')->findAll();
    }
}

The following list contains the most important remarks related to the Twig extension:

  • The string returned by the “getName”  method – “color_extension” will be used to register the extension;
  • The “getColors” method is the one which returns the entities, using the EntityManager;
  • In order to have access to the EntityManager, the Twig extension needs to be registered by specifying that the EntityManager service (identified as “doctrine.orm.entity_manager”) will be passed as argument;
  • The key “get_colors” from the array returned by the “getFunctions” method is the actual Twig function name which needs to be called in the Twig template to return the entities.

Twig extension registration:

In order to register the Twig extension the following piece of code needs to be added to src/Acme/DemoBundle/Resources/config/services.xml:

<service id="twig.extension.acme.demo_bundle.color_extension" class="Acme\DemoBundle\Twig\Extension\ColorExtension">
    <tag name="twig.extension" />
    <argument type="service" id="doctrine.orm.entity_manager" />
</service>

As previously mentioned, the “color_extension” string is used in the service id and the EntityManager service is sent as parameter for the Twig extension.

Everything should be set by now, the only thing that needs to be done is to call the “get_colors” function inside a Twig template. Here’s an example:

{% set colors = get_colors() %}
{% for color in colors %}
   <a href="javascript:alert('{{color.hex}}'); return false;">{{color.name}}</a>
{% endfor %}

The global variables alternative.

Update the Twig extension (src/Acme/DemoBundle/Twig/Extension/ColorExtension.php) with the following code:

public function getGlobals()
{
    return array('colors' => $this->getColors());
}

This means that the “colors” key will become a global variable and can be used in a Twig template.

{% for color in colors %}
    <a href="javascript:alert('{{color.hex}}'); return false;">{{color.name}}</a>
{% endfor %}

Easy file sharing with Python SimpleHTTPServer

An easy way to share files from your computer is to use Python SimpleHTTPServer. You don’t need to know Python programming to use the SimpleHTTPServer, the only requirement is to have Python installed on the machine where the files that needs to be shared are located.

An easy way to share files from your computer is to use Python SimpleHTTPServer. You don’t need to know Python programming to use the SimpleHTTPServer, the only requirement is to have Python installed on the machine where the files that needs to be shared are located.

Most Linux distributions are shipped with Python installed by default, but for Windows you might need to check how to use Python on Windows.

To start the SimpleHTTPServer “cd” into the directory which you want to be shared and run the command:

python -m SimpleHTTPServer 8000

You need to specify a port, usually 8000, like in the example should be just fine.
To access the shared files o to http://your_ip_address:8000.

Understanding file permissions and ownership on Linux

The files on a Linux system can have reading permissions, writing permissions, executing (running) permissions or no permissions for the user that owns that files, groups of users or the rest – users who does not own that files and they are not members of any group.

The files on a Linux system can have reading permissions, writing permissions, executing (running) permissions or no permissions for the user that owns that files, groups of users or the rest – users who does not own that files and they are not members of any group.

The usual file types are:

  • Directory – associated symbol d
  • Normal file – associated symbol (minus, dash)
  • Symbolic link (symlink) (like a shortcut on Windows) – associated symbol l

Permission types:

  • Reading – associated symbol r, or number 4
  • Writing – associated symbol w, or number 2
  • Executing (running) – associated symbol x, or number 1
  • No permission – associated symbol , or number 0

If a file has the reading permission you can open the file and read it, but you can not change the content. If a directory has the reading permission you can read the files in that directory, but you are not allowed to change their content.

If a file has the writing permission you can open the file for reading and for writing (you can change the file’s content and save it with the new content). You can not delete or rename a file unless the directory has the writing permission.

The execution permission allows the user to execute (run) the file (like a shell script).

User types:

  • User – the user name of the owner of the file or directory; if a user creates a file or directory it becomes the owner of that file of directory.
  • Group – a group of users (ftp, mysql), all group members have the same rights for the file or directory.
  • Other – all users that do not own the file or directory and they do not belong to any group that has right for the file or directory.

Setting permissions:

You can set the permissions using the chmod command. There two methods for changing file permissions:

  • Symbolic mode
  • Numeric mode

Symbolic mode

Setting the permissions is made using the associated symbols – rwx.

Actions are defined using mathematical symbols: the + (plus) symbol is used to add a permission, the – (minus) symbol is used to remove a permission, and the = (equal) symbol is used to remove the old permission and set a new one.

For the owners, associated symbols are u for user, g for group, o for others (the rest) and a for all.

To make a file executable type in a console:

chmod +x myfile

To remove the write permissions of the group:

chmod g-w myfile

Numeric mode

Instead of symbols, the associated number are used for setting permissions. The number for each owner will be the sum of the permissions for that owner.

To set the reading, writing and execution rights for the user you use the number 7 (4+2+1); to set the reading and writing rights for group will you use the number 6 (4+2); the reading permission for the rest (others) will be set using number 4.

The command for setting the permissions in numeric mode:

chmod 764 myfile

Here is the association between numbers and letters:

0  |  ---
1  |  --x
2  |  -w-
3  |  -wx
4  |  r--
5  |  r-x
6  |  rw-
7  |  rwx

Changing the owner:

It is done using the command chown.

To change the owner:

chown myusername myfile

To change the group and the owner:

chown mygroup:myowner myfile

To change only the group you use the command chgrp:

chgrp group myfile

Video tutorial

Check also a video tutorial about Unix File Permissions and Ownership (CHOWN, CHMOD, ETC) via Irongeek.com:

References:
TLDP.org
TUXfiles.org

Enable trackball pulse notifications for HTC Hero with CM7

How to enable trackball pulse notifications for missed calls on HTC Hero with CyanogenMod 7 (or other CM7 based ROM like the one provided by elelinux).

How to enable trackball pulse notifications for missed calls on HTC Hero with CyanogenMod 7 (or other CM7 based ROM like the one provided by elelinux).

Go to Settings -> CyanogenMod settings -> Interface  -> LED Notifications -> Unconfigured -> Missed Call -> Flash color

Select “White” and press back arrow.

Make a test using the “Flash test” option. If the trackball doesn’t work then you’re out of luck.

Save (using “Save” option) and go back.