All posts by mcrasta

Crypto-monnaies 3 : Mon secret de trader

Bienvenue pour cette série de tutoriels, en français, sur le monde des crypto-monnaies.
Récemment arrivé dans cet univers, je vais vous partager les trucs et astuces qui m’ont aidé, ou qui m’ont manqué, pour débuter sereinement.

Aujourd’hui je vais vous révéler la méthode ultime pour bien trader, garanti 100% efficace !
Vous êtes prêts ? C’est parti :

« Achetez bas, vendez haut »

Et bon courage à vous 😉

Crypto-monnaies 2 : Et la crypto-morale dans tout ça ?

Bienvenue pour cette série de tutoriels, en français, sur le monde des crypto-monnaies.
Récemment arrivé dans cet univers, je vais vous partager les trucs et astuces qui m’ont aidé, ou qui m’ont manqué, pour débuter sereinement.

Aujourd’hui, on met de coté la pratique, et on passe à la philo de comptoir !

Le bitcoin, et par extension les crypto-monnaies, ont souvent mauvaise presse, parfois à tord, parfois à raison. Listons les différentes critiques et essayons de trier le vrai du faux.

Le bitcoin n’est pas écologique : VRAI
Le bitcoin est basé sur le principe du PoW (« Proof of Work ») : pour maintenir le système fiable, il est nécessaire de « miner », de faire réaliser un très grand nombre d’opération mathématiques à des équipements spécifiques.
Conséquence de cela, la consommation électrique et le développement de matériel dédié sont énormes : pour assurer à peine 500 000 transactions par jour, la consommation est de l’ordre de celle de 35 millions de marocains (par exemple).
Vous avez bien lu : une transaction coute l’équivalent en électricité de la consommation d’une personne pendant un mois !

Heureusement, la situation n’est pas si dramatique :)
La plus grande partie des nouvelles crypto-monnaies, Ethereum en tête, sont basées sur le PoS (Proof of Stake), une manière de garantir la fiabilité du système plus légère en calcul : le couteux mining est remplacé par une vérification de l’ancienneté et de la fiabilité des participants aux réseaux.

De plus, une grande partie des échanges (pour le trading), même de bitcoins, ne sont pas réellement effectués en bitcoin, mais en « jetons », des équivalent plus léger et plus rapide à transférer.

Le bitcoin est une bulle, une pyramide de Ponzi : Probablement Vrai
Et cela ne pose de problème d’éthique que si quelqu’un vous prétend le contraire !

Si vous tenez absolument à devenir riche en tradant (ce qui est risqué et moralement douteux), autant le faire sur le marché des crypto-monnaies ou de l’art, relativement décorrélées de l’économie réelle.
Bon point : votre cupidité ne sera jamais cause de plan sociaux ou de gestion court-termiste dans les entreprises.
Mauvais point : l’argent que vous investissez ne participe à aucune production réelle.

Dans tous les cas, si le bitcoin et les crypto-monnaies sont une arnaque (légale), il y a quand même moyen d’en tirer parti, au détriment de ceux qui ont loupé leurs trades ou de ceux qui arriveront sur le marché plus tard (donc à plus cher !).

Le bitcoin participe au blanchiment d’argent sale : Plus ou moins
Le bitcoin a la réputation d’être un moyen de blanchir de l’argent sale, mais si l’on regarde le système en détail, cela semble être douteux :
– Il faut passer par un compte bancaire vérifié pour acquérir des crypto-monnaies ou recevoir des devises.
– Les transactions bitcoins sont publiques : même avec des systèmes de transactions multiples, ou (plus difficilement) avec les systèmes d’obfuscation par mutualisation, n’importe qui est capable de remonter des mouvements de fonds.
On a vu plus discret pour la mafia :)

Nul doute que certains groupes criminels ont pu massivement investir dans le bitcoin dans son jeune age, mais cela semble relativement exclu aujourd’hui, à moins d’avoir déja une banque corrompue à sa disposition et un service d’obfuscation fiable sous son contrôle.
Entre les techniciens de la mafia et ceux de la NSA, vous pariez sur qui ?

Si vous tenez à rester éloigné le plus possible des milieux criminels, évitez les crypto-monnaies utilisant des transactions secrètes, type DASH, et préférez l’Ethereum ou ses déclinaisons.
Et si vous avez des activités criminelles, démerdez-vous tout seuls 😛

Les crypto-monnaies sont stériles : Plus ou moins
Certes, la majeure partie des crypto-monnaies sont pensées comme étant des moyens d’échanges ou de spéculation, ne permettant la création d’aucune richesse réelle.
La seule valeur de ces monnaies tient à la qualité technique du système qui les portent, de la vivacité de leur communauté, et de leur capitalisation (la quantité d’argent qui a déjà été investie).
Petite exception : les « smarts-contrats », que l’on évoquera pas ici :)

En parallèle de ces monnaies « stériles », des crypto-monnaies « utiles » sont apparues : Au lieu d’enrichir les participants pour leur mining ou pour les intérêts, certaines monnaies sont distribuées en récompense de calculs utiles pour la communauté, exécutable par du matériel informatique domestique.

On notera par exemple :
Le gridcoin (GRC) : Le principe est simple, vous choisissez un projet scientifique, partagez votre puissance de calcul, puis êtes récompensés ! Les domaines étudiés sont larges : mathématiques, physiques, astronomie, chimie …
Le CureCoin (CURE) : Même principe, mais spécialisé pour l’étude de nouvelles molécules, on l’espère à but médical !
Le Golem (GNT) : Cette fois votre puissance de calcul est utilisée pour un but un peu moins noble : réaliser des animations graphiques. En effet, le système Golem permet en effet aux graphistes d’accéder à une plus grande puissance de calcul, en vous « louant » votre matériel.

Dernière catégories, certaines monnaies sont adossées non pas au travail fourni par votre ordinateur, mais par vos propres actions. Par exemple la monnaie Steem vous est distribué pour votre participation sur le réseau social Steemit, selon la popularité de vos participations (inscription actuellement désactivée).

Voilà pour cette fois, le prochain billet nous parlera de quelque chose … certainement !

Crypto-monnaies 1 : acquérir des crypto-monnaies

Bienvenue pour cette série de tutoriels, en français, sur le monde des crypto-monnaies.
Récemment arrivé dans cet univers, je vais vous partager les trucs et astuces qui m’ont aidé, ou qui m’ont manqué, pour débuter sereinement.

Aujourd’hui, on attaque par la pratique : si vous lisez ceci, c’est que vous en savez déja assez sur les crypto-monnaies pour savoir que vous voulez en acheter !

J’ai testé pour vous quelques plateformes d’achat permettant d’acquérir au moins des bitcoins, en paiement par carte bleue, depuis la France. Le but étant d’avoir un achat immédiat, pratique, pas cher, le tout avec un petit montant de départ !

Dans tous les cas, vous aurez besoin :
– d’une carte bleue (testé avec une visa electron)
– d’une mise de départ minimum, ici 50€.
– d’une piece d’identité (testé avec une carte d’identité)
– d’un smartphone ou d’une webcam de bonne qualité (un scanner peut aider si votre appareil photo est limité en résolution)

Si vous être impatient, le seul site qui m’a permis de m’en sortir vite et bien (sur 6 testés quand même !) c’est CEX.IO.

Pour les plus curieux, voila le review entier, sachant que j’avais déjà enlevé les plateformes réputées douteuses de mon tableau de chasse :

BitPanda : My tailor is rich
L’identification se fait à travers une procédure vidéo, en anglais ou en allemand, fournie par 3 entreprises de sécurisation différentes.
Manque de bol, la première n’accepte pas les cartes d’identités, la deuxieme non plus, (malgré les informations sur le site BitPanda), et la 3eme société trouvait ma webcam ou ma connexion trop faible, respectivement ADSL et HD pourtant.
Bon point : le support est très réactif, le site propose un système de dépôt en Euro,facillitant l’achat au moment opportun  et propose 6 crypto-monnaies différentes.

Changelly : Trop cher cousin …
En plus de demander un investissement minimum de 100€, ce qui est une mise déraisonnable quand on essaie les services de différents revendeurs, potentiellement frauduleux, les taux pratiqués semblaient particulièrement élevés.
Identification non-testée.

Coinbase : Ca marchait presque …
L’identification se fait par envoi de fichiers, les fichiers sont rapidement acceptés (qq heures dans mon cas).
Manque de pot, le paiement à systématiquement échoué lors de la vérification avec la banque …

CoinMama : Born Toulouse !
Les grands loosers de la série, mes documents sont en vérification depuis 2 mois et demi
#LOL

CEX.IO : The solution :)
Voici le site qui m’a finalement permis d’acquérir mes précieux BTC !
L’identification se fait en quelques minutes lors de la première commande, et permet un plafond de 500€/semaine.
En plus des fonctions d’achats simple, le site héberge une plateforme d’échange pour 9 crypto-monnaies, déclinés en €, $, £ (très bien pour voir les tendances sur les autres marchés pour ceux qui veulent « trader » !).
Vu que ces marchés sont dynamiques, ceci garanti des prix « justes », et vu que les frais de ce site sont modérés, c’est parfait.

Voilà pour le premier épisode, dans la suite nous discuterons gridcoin, micro-trading ou éco-mining, selon l’envie :)

Note : Les liens fournis contiennent des informations permettant de participer aux programmes d’affiliations proposés par les différentes plateformes.
En plus de dédommager mes quelques semaines de galères studieuses recherches, cela vous permettra, selon les plateformes, de gagner des bonus une fois inscrit :)

Prestashop : Background-image en déplacement !

Le but : Ajouter des images de fond, sur toutes les pages de notre site, et les faire se déplacer.

Ouvrons notre /themes/default-bootstrap/css/global.css et ajoutons à la fin :

@keyframes animatedFlow {
    0% { background-position: -10% -25%; }
    80% { background-position: 125% 50%; }
    80.001% { background-position: -50% -40%; }
    100% { background-position: -10% -25%; }
}
@-moz-keyframes animatedFlow {
    0% { background-position: -10% -25%; }
    80% { background-position: 125% 50%; }
    80.001% { background-position: -50% -40%; }
    100% { background-position: -10% -25%; }
}
@-webkit-keyframes animatedFlow {
    0% { background-position: -10% -25%; }
    80% { background-position: 125% 50%; }
    80.001% { background-position: -50% -40%; }
    100% { background-position: -10% -25%; }
}
@-ms-keyframes animatedFlow {
    0% { background-position: -10% -25%; }
    80% { background-position: 125% 50%; }
    80.001% { background-position: -50% -40%; }
    100% { background-position: -10% -25%; }
}
@-o-keyframes animatedFlow {
    0% { background-position: -10% -25%; }
    80% { background-position: 125% 50%; }
    80.001% { background-position: -50% -40%; }
    100% { background-position: -10% -25%; }
}

@keyframes animatedFlow2 {
    0% { background-position: 80% 50%; }
    30% { background-position: 150% 80%; }
    30.0001% { background-position: -20% 50%; }
    100% { background-position: 80% 50%; }
}
@-moz-keyframes animatedFlow2 {
    0% { background-position: 80% 50%; }
    30% { background-position: 150% 80%; }
    30.0001% { background-position: -20% 50%; }
    100% { background-position: 80% 50%; } 
}
@-webkit-keyframes animatedFlow2 { 
    0% { background-position: 80% 50%; }
    30% { background-position: 150% 80%; }
    30.0001% { background-position: -20% 50%; }
    100% { background-position: 80% 50%; }
}
@-ms-keyframes animatedFlow2 {
    0% { background-position: 80% 50%; }
    30% { background-position: 150% 80%; }
    30.0001% { background-position: -20% 50%; }
    100% { background-position: 80% 50%; }
}
@-o-keyframes animatedFlow2 {
    0% { background-position: 80% 50%; }
    30% { background-position: 150% 80%; }
    30.0001% { background-position: -20% 20%; }
    100% { background-position: 80% 50%; } 
}



@keyframes animatedFlow3 {
    0% { background-position: -25% 80%; } 
    100% { background-position: 125% 60%; }
}
@-moz-keyframes animatedFlow3 {
    0% { background-position: -25% 80%; } 
    100% { background-position: 125% 60%; }
}
@-webkit-keyframes animatedFlow3 {
    0% { background-position: -25% 80%; } 
    100% { background-position: 125% 60%; }
}
@-ms-keyframes animatedFlow3 {
    0% { background-position: -25% 80%; } 
    100% { background-position: 125% 60%; }
}
@-o-keyframes animatedFlow3 {
    0% { background-position: -25% 80%; } 
    100% { background-position: 125% 60%; }
}

body {
    background-image: url(/flo.png);
    background-repeat: no-repeat;
 
    animation: animatedFlow 60s linear infinite;
    -moz-animation: animatedFlow 60s linear infinite;
    -webkit-animation: animatedFlow 60s linear infinite;
    -ms-animation: animatedFlow 60s linear infinite;
    -o-animation: animatedFlow 60s linear infinite;
}

.columns-container{
    background-image: url(/flo2.png);
    background-repeat: no-repeat;
    animation: animatedFlow2 100s linear infinite;
    -moz-animation: animatedFlow2 100s linear infinite;
    -webkit-animation: animatedFlow2 100s linear infinite;
    -ms-animation: animatedFlow2 100s linear infinite;
    -o-animation: animatedFlow2 100s linear infinite;
}

#page {
    /*background-color:#bbee80;*/
    background-image: url(/flo3.png);
    background-repeat: no-repeat;
 
    animation: animatedFlow3 80s linear infinite; 
    -moz-animation: animatedFlow3 80s linear infinite;
    -webkit-animation: animatedFlow3 80s linear infinite;
    -ms-animation: animatedFlow3 80s linear infinite;
    -o-animation: animatedFlow3 80s linear infinite;
}

Vu qu’on ne peut ajouter qu’une image de fond par conteneur, donc body, #page et .columns-container, ça nous fait que 3 images mobiles sans modification plus profonde du site.

C’est pas mal, mais on pourrait vouloir que nos images commencent leur déplacement sur une position visible, au lieu d’apparaitre hors champ. Voila une petite astuce pour modifier nos animations :

@keyframes animatedFlow2 {
    0% { background-position: 80% 50%; }
    30% { background-position: 150% 80%; }
    30.0001% { background-position: -20% 50%; }
    100% { background-position: 80% 50%; }
}
@-moz-keyframes animatedFlow2 {
    0% { background-position: 80% 50%; }
    30% { background-position: 150% 80%; }
    30.0001% { background-position: -20% 50%; }
    100% { background-position: 80% 50%; } 
}
@-webkit-keyframes animatedFlow2 { 
    0% { background-position: 80% 50%; }
    30% { background-position: 150% 80%; }
    30.0001% { background-position: -20% 50%; }
    100% { background-position: 80% 50%; }
}
@-ms-keyframes animatedFlow2 {
    0% { background-position: 80% 50%; }
    30% { background-position: 150% 80%; }
    30.0001% { background-position: -20% 50%; }
    100% { background-position: 80% 50%; }
}
@-o-keyframes animatedFlow2 {
    0% { background-position: 80% 50%; }
    30% { background-position: 150% 80%; }
    30.0001% { background-position: -20% 20%; }
    100% { background-position: 80% 50%; } 
}

Ca se passe de commentaires, à un houra pour moi près :)

Prestashop : Ajouter un client à un groupe automatiqument !

Suite aux précédent billets, nous sommes les heureux possesseurs d’un prestashop tuné, capable de cacher certaines pages et de désactiver certains produits aux utilisateurs n’ayant pas le niveau suffisant.

Ne reste plus qu’a modifier automatiquement les groupes des utilisateurs, suite à l’achat d’un certain produit, disons un ticket d’entrée.

Premiere étape, modifier nos produits pour définir lesquels attribue un nouveau groupe au client, et quel groupe.

BDD :

Créons un champ « nlvl »  int(3) dans la table ps_products, juste apres le champ xlvl du precedent tuto.

Modification du produit :

Reprenons le precedent tuto, en changeant chaque occurrence de « xlvl » par « nlvl ».
N’oublions pas de changer les descriptions, « Niveau de sécurité minimum »  devient « Nouveau groupe client (0 pour désactiver) »

A ce stade, nous devrions pouvoir affecter notre parametres « nouveau groupe » à nos produits via le back office.

Rendons maintenant le mécanisme actif !

Attribution du nouveau groupe

Le code suivant pourrait s’intégrer à plusieurs endroits du processus de commande.  Nous, nous allons choisir de squatter le processus orderHistory.  Quelque soit le canal de paiement, on peut se fier la bonne execution de ce code, pour n’importe quel statut de commande confirmant le paiement (ps_order_status => is_paid)

Editons classes/order/OrderHistory.php et ajoutons ceci juste apres  »        if ($new_os->paid == 1) { »

$customer = new Customer((int)$order->id_customer);
            foreach ($order->getProductsDetail() as $product) {
                $proct = new Product($product['product_id']);
                if($customer->id_default_group < $proct->nlvl){
                    Db::getInstance()->execute('UPDATE `'._DB_PREFIX_."customer` SET id_default_group='".(int)$proct->nlvl."' WHERE `id_customer` = '".(int)$order->id_customer."'");
                    Db::getInstance()->execute('INSERT INTO `'._DB_PREFIX_."customer_group` (`id_group`, `id_customer`) VALUES ('".(int)$proct->nlvl."','".(int)$order->id_customer."')");
                    break;
                }
            }

Citons Joey Starr pour finir : « Big up a moi-même ! »

 

linux : Search in files script

A super linux ability : find files containing certain words.
but typing the command (even remembering it! ) is anoying.
Lets create a quick script to ease the use !

sudo nano /usr/bin/myfind

#!/bin/bash
if [ $# -eq 0 ]
  then
    echo "No arguments supplied"
    exit;
fi
grep -rnw -A1 -B1 './' -e "$1"

Type : myfind aword
to list every file containing « aword » in the current directory and his subfolders (recursive !)

Prestashop : Produits privés

De la même manière qu’on a pu modifier nos pages cms pour les rendre privées, en se basant sur le groupe principal de l’utilisateur, modifions également nos pages produits pour désactiver l’ajout au panier aux clients non autorisés.

Dans notre cas, on veux que nos clients puisse voir le produit, mais que seuls certains puissent le commander. La manip est donc à adapter à nos besoin. D’ailleurs, tout ceci n’est qu’une ré-application de l’article précédent.

Base de donnée :

Pas de problème ici, nous allons juste rajouter un champ à la table « ps_product», qui correspondra au niveau de groupe minimum pour voir la page. Appelons le « xlvl »,   INT (3) avec 0 en valeur par défaut, pour que toutes nos pages soient publiques par défaut.
Plaçons le juste après le champ « ean13 », par acquis de conscience.
Rappel : Nos id_group sont, classiquement, (1=>visiteurs, 2=>invités, 3=>clients, 4=>membre, 5=>associé ) pour ce projet.

Classes :

Pas de soucis ici non plus, on édite « /classes/Product.php ». Pas d’override, on est des fous !
Pour commencer, ajoutons nos défintions de variable :

    public $clvl;
    public $xlvl;

Dans la définition de notre objet $definition,, ajoutons la ligne :

            'xlvl' =>            array('type' => self::TYPE_INT),

Pendant que nous sommes sur cette page, ajoutons une nouvelle méthode, chargée de retourner le niveau de l’utilisateur dans nos pages :

public static function getclvl(){
    global $cookie;
    if(isset($cookie->clvl)) {return $cookie->clvl;}
    else return 1;
}

 

Cookie :

Comme dans le tuto précédent, modifions /controllers/front/AuthController.php, pour ajouter cette ligne dans la méthode processSubmitLogin().

$this->context->cookie->clvl = $customer->id_default_group;

et cette ligne dans updateContext():

        $this->context->cookie->clvl=$customer->id_default_group;

Modifier ensuite classes/Cookie.php pour y ajouter cette ligne, dans mylogout() :

        unset($this->_content['clvl']);

 

Controller :

Cette fois ça va saigner !
On va se coller a la définition de ean13, qui m’a servi de fil rouge pour trouver comment faire, et qui nous guidera pour la position de notre xlvl dans les listes ( toujours entre ean13 et upc )

Ouvrons « controllers/admin/AdminProductsController.php » et ajoutons ceci à la fin de la définition de $this->fields_list, dans public function __construct()

           $this->fields_list['xlvl']=array(
            'title' => 'Niveau d\'accès minimum',
            'type' => 'int',
        );

Dans processProductAttribute, la définition devient

$array_checks = array(
                'reference' => 'isReference',
                'supplier_reference' => 'isReference',
                'location' => 'isReference',
                'ean13' => 'isEan13',
                'xlvl'=> 'isInt',
                'upc' => 'isUpc',
                'wholesale_price' => 'isPrice',
                'price' => 'isPrice',
                'ecotax' => 'isPrice',
                'quantity' => 'isInt',
                'weight' => 'isUnsignedFloat',
                'unit_price_impact' => 'isPrice',
                'default_on' => 'isBool',
                'minimal_quantity' => 'isUnsignedInt',
                'available_date' => 'isDateFormat',
            );

// passons queqlues ligne
                                //Tools::getValue('attribute_ean13'),  Tools::getValue('attribute_xlvl'),                             //$this->isProductFieldUpdated('attribute_default') ? Tools::getValue('attribute_default') : null,

// et encore quelques lignes

// null,
// Tools::getValue('attribute_ean13'),
 Tools::getValue('attribute_xlvl'),

Penchons nous sur initFormInformations() et modifions sa liste ainsi :

 array_push($product_props,
 'price', 'wholesale_price', 'id_tax_rules_group', 'unit_price_ratio', 'on_sale',
 'unity', 'minimum_quantity', 'additional_shipping_cost',
 'available_now', 'available_later', 'available_date'
 );

la liste de renderListAttributes() devient

 $this->fields_list = array(
            'attributes' => array('title' => $this->l('Attribute - value pair'), 'align' => 'left'),
            'price' => array('title' => $this->l('Impact on price'), 'type' => 'price', 'align' => 'left'),
            'weight' => array('title' => $this->l('Impact on weight'), 'align' => 'left'),
            'reference' => array('title' => $this->l('Reference'), 'align' => 'left'),
            'ean13' => array('title' => $this->l('EAN-13'), 'align' => 'left'),
            'xlvl' => array('title' => 'niveau d\'acces necessaire', 'align' => 'left'),
            'upc' => array('title' => $this->l('UPC'), 'align' => 'left')
        );

// on ajoutera également ça un peu plus loin dans la fonction, je vous laisse trouver ou :p
                    $comb_array[$combination['id_product_attribute']]['xlvl'] = $combination['xlvl'];

 

Et ceci dans renderForm(), par exemple en dessous de la definition du switch active,  pour avoir notre gestion en back office.

,
                array(
                    'type' => 'text',
                    'label' => "Niveau de sécurité",
                    'name' => 'plvl',
                    'required' => false,
                    'hint' => array(
                        $this->l('Taper 0 pour des pages visibles par tous, 4 pour des pages réservés aux membres et associés, 5 pour les pages réservées aux associés')
                    ),
                )

 

Templates :

Presque fini ! Editons le template product.tpl dans le dossier de votre theme.
Ajoutons cette condition avant la déclaration du div « box-cart-bottom » :

{if $product->getclvl()>$product->xlvl}

Et ceci apres

        {else}
            <p>Vous ne pouvez pas encore commander ce produit</p>
        {/if}

 

Pour le backoffice, modifions /adminXXX/theme/default/template/controllers/products/information.tpl  et ajoutez ce champ là où ça vous chante (il faut chanter juste quand même !)

    <div class="form-group">
        <label class="control-label col-lg-3" for="xlvl">
            <span class="label-tooltip" data-toggle="tooltip"
                title="{l s='Niveau de sécurité necessaire : 0 pour tous, 3 pour pages reservées aux membre & associé, 4 pour les associés'}">
                {$bullet_common_field} {l s='Niveau de sécurité minimum'}
            </span>
        </label>
        <div class="col-lg-3">
            <input maxlength="13" type="text" id="xlvl" name="xlvl" value="{$product->xlvl|htmlentitiesUTF8}" />
        </div>
    </div>

Ca avait l’air plus compliqué sans le tuto !

Prestashop : Pages CMS privées

Aloha !
aujourd’hui, on se bat avec prestashop !
Objectif : Limiter l’acces de certaines pages CMS a certains groupes de clients.
La méthode : quick & dirty, codage en dur des groupes autorisés, et choix techniques aléatoires ! Ayant 0 expérience  sur smarty , ça n’aide pas à avoir du recul ..

Mais peu importe :]

Base de donnée :

Pas de probleme ici, nous allons juste rajouter un champ à la table « ps_cms », qui correspondra au niveau de groupe minimum pour voir la page. Appellons le « plvl »,   INT (3) avec 0 en valeur par défaut, pour que toutes nos pages soient publiques par défaut.
Nos id_group sont, classiquement, (1=>visiteurs, 2=>invités, 3=>clients). Nous aurons également (4=>membre, 5=>associé ) pour ce projet.

Classes :

Pas de soucis ici non plus, on édite « /classes/CMS.php ». Pas d’override, on est des fous !
Pour commencer, ajoutons nos défintions de variable :

    public $plvl;
    public $clvl;

Dans la définition de notre objet cms[« fields »], apres la définitation de « active », ajoutons la ligne :

            'plvl' =>            array('type' => self::TYPE_INT),

 

Controller :

Ouvrons « controllers/admin/AdminCmsController.php » et ajoutons ceci dans à la fin de la définition de $this->fields_list

            , 'plvl' => array('title' => $this->l('Niveau d\'accès minimum'))

Et ceci dans renderForm(), par exemple en dessous de la definition du switch active,  pour avoir notre gestion en back office.

,
                array(
                    'type' => 'text',
                    'label' => "Niveau de sécurité",
                    'name' => 'plvl',
                    'required' => false,
                    'hint' => array(
                        $this->l('Taper 0 pour des pages visibles par tous, 4 pour des pages réservés aux membres et associés, 5 pour les pages réservées aux associés')
                    ),
                )

Cookie :

Pour que notre id_group soit disponible au chargement de la page, il va nous falloir passer par les cookies. Gestion de la création, destruction et mise à jour donc (tout un programme … lol ). Modifions /controllers/front/AuthController.php, pour ajouter cette ligne dans la méthode processSubmitLogin().

$this->context->cookie->clvl = $customer->id_default_group;

et cette ligne dans updateContext():

        $this->context->cookie->clvl=$customer->id_default_group;

Modifier ensuite classes/Cookie.php pour y ajouter cette ligne, dans mylogout() :

        unset($this->_content['clvl']);

et ajoutons une méthode à la classe cms (/classes/CMS.php)

public static function getclvl(){
    global $cookie;
    if(isset($cookie->clvl)) {return $cookie->clvl;}
    else return 1;
}

 

Template :

Presque fini ! Editons le template cms.tpl dans le dossier de votre theme.
Remplacons :

    <div class="rte{if $content_only} content_only{/if}">
        {$cms->content}
    </div>

par :

    <div class="rte{if $content_only} content_only{/if}">
       {if $cms->getclvl()>$cms->plvl}
            {$cms->content}
        {else}
            <p>Vous ne pouvez pas acceder à cette page.</p>
        {/if}
    </div>

Voila une MAJ un peu sauvage qui va bien !
Peut-être y avait t’il moyen de procéder sans les cookies ?

Neural Network – Let’s dub

From noobs to nerds, everyone has been told about neural network. But did you ever play with?

Let’s avoid the MNIST tutorial (handwritten digit recogntion), too boring, and choose something more exciting : music recognition ! Style, instrument, notes, effects, all of this would be nice to extract from mp3 !

Step 1 : find data
We need a lot of data for any kind of recognition. Of course we need music, and also a massive pack of  instrument sample . Let’s start by classifying our datas, each instrument in a folder of it’s name.
Step2 : generate more datas.
1500 samples is not that too bad, but what about getting a lot more ? In visual recognition, we would slightly distort our sample image, let’s do the same on our musical samples.
Now apply chorus, reverb and then filter for getting more realistic samples.
Step 3 : prepare datas
As working on wav file would be painful, let’s transform our sample into representative images, for say spectrogram. As this project has never been documented, we will have to try or to combine different visualisation parameters.
Using Sox, we will get a DFT spectrogram, and use Hamming windows for the frequency analysis, and have to try the Dolph windows for dynamic analysis. For an human eye, the « peak spectrometer » seems also representative, let’s keep an eye on it.

I’m currently using a sh script for crawling music folder, i’ll release it soon here.

Step 4 : Build a brain I : Skull
Now we have to setup the tools to contain and manage our neural network.
I tried TensorFlow, wich works fine but lacks by it’s user-interface, in combination with mnisten, in order to package custom datas in MNIST format.
But even geeks needs some kindness, so we will use NVIDIA’s Digits and their Caffe fork, wich implement multiple neural network sample and tools for data formatting, the whole thing managed via a local webpage.

Building digits and caffe wasn’t so easy,  here’s a short list of command to get it work on a fresh ubuntu 14.04.

 Without CUDA

cd $HOME
sudo apt-get install python-pil python-numpy python-scipy python-protobuf \ python-gevent python-flask python-flaskext.wtf gunicorn python-h5py \
libgflags-dev libgoogle-glog-dev libopencv-dev \
libleveldb-dev libsnappy-dev liblmdb-dev libhdf5-serial-dev \
libprotobuf-dev protobuf-compiler libatlas-base-dev \
python-dev python-pip python-numpy gfortran
sudo apt-get install –no-install-recommends libboost-all-dev
git clone https://github.com/NVIDIA/DIGITS.git digits
export $DIGITS_HOME=$HOME/digits
wget https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
cd $DIGITS_HOME
sudo pip install -r requirements.txt
cd $HOME
git clone –branch caffe-0.14 https://github.com/NVIDIA/caffe.git
export CAFFE_HOME=${HOME}/caffe
sudo apt-get install
cd $CAFFE_HOME
cat python/requirements.txt | xargs -n1 sudo pip install
cd $CAFFE_HOME

sed -i ‘$aCPU_ONLY := 1’ Makefile.config
make all
make test
make runtest
sudo pip install –upgrade Flask-WTF
cd $DIGITS_HOME

With CUDA

CUDA_REPO_PKG=cuda-repo-ubuntu1404_7.5-18_amd64.deb && wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1404/x86_64/$CUDA_REPO_PKG && sudo dpkg -i $CUDA_REPO_PKG

ML_REPO_PKG=nvidia-machine-learning-repo_4.0-2_amd64.deb && wget http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1404/x86_64/$ML_REPO_PKG && sudo dpkg -i $ML_REPO_PKG

sudo apt-get update
sudo apt-get install digits

Warning  : Training new models on caffe/digits without CUDA is very slow. Our case took more than a week on ImageNet !
If you’re not the owner of a CUDA-compatible nvidia graphic card, you’ll have to spend from 50$ to 25000$ to go further, or use pretrained models.

Step 5 : Build a brain II : external wiring
Let see our goals again : Get Mp3 file as input, Output MIDI file. In the same time, Caffe get images as input and output raw log.
We will basically need 2 programs, let’s say inputter, for spectrographing  a mp3, and launching our tests. The second, outputter, will assume the conversion to MIDI format.

Step 6 : Build a brain III, or 470 !
Take a look on the parameters we want to extract for each instrument note :
– Note duration (attack – sustain – release  events)
– Pitch (or note)
– Velocity / Volume
– Instrument sub-category / style
– Filter
– Reverb
Many of these parameters can easily be calculated when we use monophonic tracks, but in our polyphonic case we will rely on our neural networks from the A to the Z, we came for that ! Sadly, the amount of combination still exceed what a poor computer like ours can do (it would take a 47 million category model to achieve the aimed resolution below ).

// hypothetical way
//Let’s split our job.
//First, what about using one model per instrument ? Better, let’s split their job in 3 :
// Score, instrumentation and effects.
//Score will detect around  : 40 notes * 3 events * 8 volumes = 960 cats  #may vary for polyphonic instrument
//Instrumentation : 20 sub instruments * 50 filters = 1000 cats
//Effects : 12 delays * 5 reverbs * 15 filters = 900 cats

let’s first try to recognize drum and percussions hits. Results in 15 hours ^^ »
Still training, and  get 92% accuracy … Looks promising  !

The MZ61581 PI EXT 2015.12.12 case

Hi mates !

Let’s try to make this LCD screen working on linux raspbian wheezy. Symptoms on first tests were slow fps, or image distorsion.

First attempt : Let’s follow the official setup guide

sudo apt-get update
sudo apt-get upgrade
* coffee time *

sudo reboot
cd /boot/overlays
sudo mv mz61581-overlay.dtb old-mz61581-overlay.dtb
sudo wget http://www.itontec.com/mz61581-overlay.dtb
sudo nano /boot/config.txt

Add to the bottom :

dtparam=spi=on
dtoverlay=mz61581,debug=32

Save & reboot.
Result : slow fps. might have only 4k DMA memory  ?

Second attempt : What was that default driver ?
It seems that wheezy aldready provided us a mz61581-overlay.dtb file.
Let’s try again the official guide, but now ommit the rm / wget part.
Maybe this old driver would fit better ? (quick answer, no)
Mayber the new raspbian provided mz-overlay.dtb would be better (no again)

Third attempt : Notro our savior !

Working on the previous version of the MZ61581-PI-EXT, i had poor performance until using notro’s work. Let’s take a look on his wiki:
fbtft_device route  : tried
« sudo modprobe fbtft_device name=mz61581 » but mz61581 is only an overlay, not a fbtft official device.
« sudo modprobe fbtft_device name=tontec35_9481 » and « sudo modprobe fbtft_device name=tontec35_9486 », only get the backlight working.
Mz61581 is not one of these !

Forth attempt : woohoo!

Dtoverlay route:
To use the new spi bcm2835 with dma support, let’s disable old spi enabling in /boot/config.txt :
#dtoverlay=spi=on
dtoverlay=mz61581,speed=64000000
Be sure to use a 32Kb buffer version of mz61581-overlay.dtb !

This works !


Test protocol :

wget http://fredrik.hubbe.net/plugger/test.mpg
sudo apt-get install mencoder mplayer2
mencoder test.mpg -ovc lavc -lavcopts vcodec=mpeg4 -vf scale=480:320 -o test_480_320.mpg
mplayer -nolirc -vo fbdev2:/dev/fb1 test_480_320.mpg



 

Results :
New Tontec drivers have poor performances, but are working.
Old drivers have better performance, but are not fully compatible with the new MZ61581-PI-EXT 2015.12.12.

1) Tontec driver : With config.txt : dtparam=mz61581,debug=32
Laggy display

lsmod
Module                  Size  Used by
cfg80211              419759  0
rfkill                 16659  1 cfg80211
snd_bcm2835            19739  0
snd_pcm                74833  1 snd_bcm2835
snd_seq                53470  0
snd_seq_device          3650  1 snd_seq
snd_timer              18164  2 snd_pcm,snd_seq
snd                    52116  5 snd_bcm2835,snd_timer,snd_pcm,snd_seq,snd_seq_device
joydev                  9047  0
fb_s6d02a1              3540  0
fbtft                  27517  1 fb_s6d02a1
syscopyarea             2789  1 fbtft
sysfillrect             3313  1 fbtft
sysimgblt               1837  1 fbtft
fb_sys_fops             1149  1 fbtft
ads7846                11340  0
hwmon                   2927  1 ads7846
spi_bcm2708             5149  0
bcm2835_gpiomem         3023  0
uio_pdrv_genirq         2966  0
evdev                  10226  2
uio                     8228  1 uio_pdrv_genirq

[    3.863542] bcm2708_spi 3f204000.spi: master is unqueued, this is deprecated
[    3.888126] bcm2708_spi 3f204000.spi: SPI Controller at 0x3f204000 (irq 80)
[    4.013842] ads7846 spi0.1: touchscreen, irq 484
[    4.027389] input: ADS7846 Touchscreen as /devices/platform/soc/3f204000.spi/spi_master/spi0/spi0.1/input/input1
[    4.034035] fbtft: module is from the staging directory, the quality is unknown, you have been warned.
[    4.038912] fb_s6d02a1: module is from the staging directory, the quality is unknown, you have been warned.
[    4.076110] fbtft_of_value: width = 320
[    4.085907] fbtft_of_value: height = 480
[    4.092665] fbtft_of_value: buswidth = 8
[    4.099748] fbtft_of_value: debug = 3
[    4.105815] fbtft_of_value: rotate = 270
[    4.112181] fbtft_of_value: fps = 30
[    4.126520] fb_s6d02a1 spi0.0: fbtft_request_one_gpio: ‘reset-gpios’ = GPIO15
[    4.136612] fb_s6d02a1 spi0.0: fbtft_request_one_gpio: ‘dc-gpios’ = GPIO25
[    4.146366] fb_s6d02a1 spi0.0: fbtft_request_one_gpio: ‘led-gpios’ = GPIO18
[    4.155397] fb_s6d02a1 spi0.0: fbtft_verify_gpios()
[    4.162032] fb_s6d02a1 spi0.0: fbtft_init_display_dt()
[    4.169080] fb_s6d02a1 spi0.0: fbtft_reset()
[    4.297532] fb_s6d02a1 spi0.0: init: write_register: B0 00
[    4.304769] fb_s6d02a1 spi0.0: init: write_register: 11
[    4.311458] fb_s6d02a1 spi0.0: init: msleep(255)
[    4.582945] fb_s6d02a1 spi0.0: init: write_register: B3 02 00 00 00
[    4.590654] fb_s6d02a1 spi0.0: init: write_register: C0 13 3B 00 02 00 01 00 43
[    4.599359] fb_s6d02a1 spi0.0: init: write_register: C1 08 16 08 08
[    4.606934] fb_s6d02a1 spi0.0: init: write_register: C4 11 07 03 03
[    4.614425] fb_s6d02a1 spi0.0: init: write_register: C6 00
[    4.621006] fb_s6d02a1 spi0.0: init: write_register: C8 03 03 13 5C 03 07 14 08 00 21 08 14 07 53 0C 13 03 03 21 00
[    4.633602] fb_s6d02a1 spi0.0: init: write_register: 35 00
[    4.640307] fb_s6d02a1 spi0.0: init: write_register: 36 A0
[    4.647034] fb_s6d02a1 spi0.0: init: write_register: 3A 55
[    4.653747] fb_s6d02a1 spi0.0: init: write_register: 44 00 01
[    4.660693] fb_s6d02a1 spi0.0: init: write_register: D0 07 07 1D 03
[    4.668133] fb_s6d02a1 spi0.0: init: write_register: D1 03 30 10
[    4.675296] fb_s6d02a1 spi0.0: init: write_register: D2 03 14 04
[    4.682411] fb_s6d02a1 spi0.0: init: write_register: 29
[    4.688689] fb_s6d02a1 spi0.0: init: write_register: 2C
[    4.694942] fb_s6d02a1 spi0.0: set_var()
[    4.707942] random: nonblocking pool is initialized
[    4.901920] fb_s6d02a1 spi0.0: Display update: 1484 kB/s (202.020 ms), fps=0 (0.000 ms)
[    4.912125] fb_s6d02a1 spi0.0: fbtft_register_backlight()
[    4.919447] graphics fb1: fb_s6d02a1 frame buffer, 480×320, 300 KiB video memory, 4 KiB DMA buffer memory, fps=33, spi0.0 at 128 MHz
[    4.933895] fb_s6d02a1 spi0.0: fbtft_backlight_update_status: polarity=0, power=0, fb_blank=0

1) Tontec driver : With config.txt : dtparam=mz61581,fps=50,debug=32
Laggy display too
[ 5.174915] graphics fb1: fb_s6d02a1 frame buffer, 480×320, 300 KiB video memory, 4 KiB DMA buffer memory, fps=50, spi0.0 at 128 MHz
[   66.306436] fb_s6d02a1 spi0.0: Display update: 1475 kB/s (203.191 ms), fps=4 (239.998 ms)
[   66.481634] fb_s6d02a1 spi0.0: Display update: 1893 kB/s (158.398 ms), fps=4 (219.991 ms)

2) Rpi Driver : With config.txt : dtparam=mz61581,debug=32
Eurêka, we new have a good fps. Sadly,  there is some weird effect on the display, coor distorsion, strange transparent waves drawn over the image.

[ 3.809940] gpiomem-bcm2835 3f200000.gpiomem: Initialised: Registers at 0x3f2 00000
[ 3.859648] spi spi0.1: setting up native-CS1 as GPIO 7
[ 3.953568] spi spi0.0: setting up native-CS0 as GPIO 8
[ 4.233484] ads7846 spi0.1: touchscreen, irq 484
[ 4.243750] fbtft: module is from the staging directory, the quality is unkno wn, you have been warned.
[ 4.247379] fb_s6d02a1: module is from the staging directory, the quality is unknown, you have been warned.
[ 4.278306] input: ADS7846 Touchscreen as /devices/platform/soc/3f204000.spi/ spi_master/spi0/spi0.1/input/input1
[ 4.297086] fbtft_of_value: width = 320
[ 4.308640] fbtft_of_value: height = 480
[ 4.320960] fbtft_of_value: buswidth = 8
[ 4.333180] fbtft_of_value: debug = 32
[ 4.350623] fbtft_of_value: rotate = 270
[ 4.361306] fbtft_of_value: fps = 30
[ 4.371700] fbtft_of_value: txbuflen = 32768
[ 4.797830] fb_s6d02a1 spi0.0: Display update: 12591 kB/s (23.825 ms), fps=0 (0.000 ms)
[ 4.812592] graphics fb1: fb_s6d02a1 frame buffer, 480×320, 300 KiB video mem ory, 32 KiB DMA buffer memory, fps=33, spi0.0 at 128 MHz
[ 324.706973] fb_s6d02a1 spi0.0: Display update: 12671 kB/s (23.673 ms), fps=20 (49.978 ms)
[ 324.766897] fb_s6d02a1 spi0.0: Display update: 12662 kB/s (23.692 ms), fps=16 (59.906 ms)

2) Rpi Driver : With config.txt : dtparam=mz61581,fps=50,debug=32

The FPS is better, the glitchs remains.
[ 65.625644] fb_s6d02a1 spi0.0: Display update: 13373 kB/s (22.432 ms), fps=25 (39.992 ms)
[ 65.665652] fb_s6d02a1 spi0.0: Display update: 13370 kB/s (22.438 ms), fps=24 (40.003 ms)

Tried with fps=15 in config.txt, same glitchs happens.

After update

[ 4.592106] bcm2835-rng 3f104000.rng: hwrng registered
[ 4.603414] gpiomem-bcm2835 3f200000.gpiomem: Initialised: Registers at 0x3f200000
[ 4.630936] bcm2708_spi 3f204000.spi: master is unqueued, this is deprecated
[ 4.651956] bcm2708_spi 3f204000.spi: SPI Controller at 0x3f204000 (irq 80)
[ 4.701122] ads7846 spi0.1: touchscreen, irq 484
[ 4.706262] fbtft: module is from the staging directory, the quality is unknown, you have been warned.
[ 4.709738] fb_s6d02a1: module is from the staging directory, the quality is unknown, you have been warned.
[ 4.743410] input: ADS7846 Touchscreen as /devices/platform/soc/3f204000.spi/spi_master/spi0/spi0.1/input/input1
[ 4.762299] fbtft_of_value: width = 320
[ 4.772315] fbtft_of_value: height = 480
[ 4.783039] fbtft_of_value: buswidth = 8
[ 4.792916] fbtft_of_value: debug = 32
[ 4.802531] fbtft_of_value: rotate = 270
[ 4.812214] fbtft_of_value: fps = 15
[ 5.239950] random: nonblocking pool is initialized
[ 5.452605] fb_s6d02a1 spi0.0: Display update: 1225 kB/s (244.778 ms), fps=0 (0.000 ms)
[ 5.468757] graphics fb1: fb_s6d02a1 frame buffer, 480×320, 300 KiB video memory, 4 KiB DMA buffer memory, fps=16, spi0.0 at 128 MHz