JavaScript Formula Parser

Ich habe in JavaScript einen Formel-Parser geschrieben, welcher einen String in ein Formel-Objekt zerlegt und dieses dann evaluieren kann. Der Formel-Parser unterstützt Ausdrücke wie:

sin(x*(PI/2))*pow(x,3)*sqrt(x)

Siehe http://www.alexi.ch/jsformulaparser/formula.html für ein Demo und den Source-Code. Der Parser benützt jQuery und die flot-Library, welche auf jQuery aufsetzt, sowie das HTML5-Canvas-Objekt. Browser, welche dies nicht unterstützen, sehen leider nichts.

Screen:

JS Formula Parser

Posted in techblog | Tagged , , , , | Kommentare deaktiviert

SVN commit -m für Faule

Kleiner Proxy für das Erstellen von SVN-Commit-Meldungen. Bezieht folgende Quellen:

  • http://whatthecommit.com
  • ein lokales “vommit.txt”-File

Aufruf durch:

  • svnvommit.php: Liefert Random-Text
  • svnvommit.php?cmd=svn: Liefert fertige SVN Commit-Kommandozeile mit Message
  • svnvommit.php?help: Liefert eine Hilfe

SVN-Commit BASH-Alias:

alias svnvommit='TXT=$(curl -s http://82.197.187.164/svnvommit.php);echo "MSG ${TXT}"; svn commit -m "${TXT}"'

Beispiel unter:

http://www.alexi.ch/svnvommit.php

<?php
/**
 * SVN Velocity Commit - commit without caring about a comment
 *
 * (c) 2012 alex schenkel
 */

$sentenceFunctions = array(
	'whatthecommit' => 20,
	'localvommits' => 2,
	'cowsay' => 10,
	'fortune' => 2
);

header('Content-Type: text/plain');

// step 0: help / list required?:
if (isset($_REQUEST['help'])) {
	printHelp();
	exit;
}

if (isset($_REQUEST['sentences'])) {
	printSentences();
	exit;
}
$func = null;
if (isset($_REQUEST['sentence'])) {
	$func = $_REQUEST['sentence'];
}

// step 1: find which sentence function to use: the higher propability the more
// it would be taken:
if (!$func) {
	$sumProb = 0;
	foreach($sentenceFunctions as $val) {
		$sumProb += max(0,(int)$val);
	}
	$func = null;
	$rnd = rand(1,$sumProb);
	$prob = 0;
	foreach($sentenceFunctions as $f=>$val) {
		$prob += max(0,(int)$val);
		$func = $f;
		if ($prob >= $rnd) {
			//echo "$prob, $rnd";
			break;
		}
	}
}
if (!function_exists($func)) {
	echo "ERROR: CHECK YOUR VELOCITY COMMIT SERVICE AT {$_SERVER['SERVER_NAME']}! SOMETHING WENT WRONG!";
	exit;
}

// Step 2: get the message from the sentence provider:
$text = $func();

// Step 3: output, either with or without command line wrapping:
if (isset($_REQUEST['cmd'])) {
	switch ($_REQUEST['cmd']) {
	case 'svn': $text = 'svn commit -m "'.addslashes($text).'"'; break;
	case 'git': $text = 'git commit -m "'.addslashes($text).'"'; break;
	case 'git-add': $text = 'git commit -a -m "'.$text.'"'; break;
	}
}

echo $text;
exit;

function printHelp() {
	echo <<<EOT
Known parameters:
    help           : this list
    sentences      : List of available sentence sources
    sentence=<name>: uses only the <name> sentence source
    cmd=svn        : Wraps the output in a SVN commit command line
    cmd=git        : Wraps the output in a GIT commit command line
    cmd=git-add    : Wraps the output in a git -a commit command line
EOT;
}

function printSentences() {
	global $sentenceFunctions;
	foreach($sentenceFunctions as $f=>$val) {
		echo "{$f}\n";
	}
}

function whatthecommit() {
	$text = file_get_contents('http://whatthecommit.com/');
	try {
		$xml = new SimpleXMLElement($text);
		$elems = $xml->xpath("//*[@id='content']");
		$text = trim(preg_replace("/[\n\"]/",'',(string)$elems[0]->p[0]));

		return "WTC: ".$text;
	} catch (Exception $e) {
		return false;
	}
	return $text;
}

function localvommits() {
	return "V-OMMIT: ".getVommitsTxtLine();
}

function cowsay() {
	$cowsaycmd = '/opt/local/bin/cowsay';
	$txt = getVommitsTxtLine();
	$h = popen("{$cowsaycmd} \"{$txt}\"",'r');
	if ($h) {
		$ret = "The cow says:\n";
		while (($line = fgets($h)) !== FALSE) {
			$ret .= $line;
		}
		$code = pclose($h);
		if ($code == 0) {
			return str_replace('"','',$ret);
		}
	}
	return $txt;
}

function getVommitsTxtLine() {
	$vommits = array();
	$fh = @fopen(dirname(__FILE__).'/vommits.txt','r');
	if ($fh) {
		while (($line = fgets($fh)) !== FALSE) {
			$line = trim(preg_replace("/[\n\"]/",'',$line));
			if ($line) {
				$vommits[] = $line;
			}
		}
		fclose($fh);
	}
	if (count($vommits) > 0) {
		$text = $vommits[rand(0,count($vommits)-1)];
	} else $text = '<empty vommits.txt file....>';

	return $text;
}

function fortune() {
	$fortunecmd = '/opt/local/bin/fortune';
	$h = popen("{$fortunecmd}",'r');
	$txt = "Today's Fortune:\n";
	if ($h) {
		$ret = "";
		while (($line = fgets($h)) !== FALSE) {
			$txt .= $line;
		}
		$code = pclose($h);
		if ($code == 0) {
			$txt = str_replace('"','',$txt);
		}
	}
	return $txt;
}
Posted in techblog | Kommentare deaktiviert

Mein Standard-ANT-Build-Script

Das folgende XML-File ist mein Standard-ant-Build-Script, welches ich immer mal wieder als Skeleton benutze:

<?xml version="1.0" encoding="UTF-8"?>
<project name="jDirSize" default="all" basedir=".">
	<property name="src" value="src" />
	<property name="build.dir" value="build" />
	<property name="lib.dir" value="lib" />
	<property name="classes.dir" value="${build.dir}/classes" />
	<property name="jar.dir" value="${build.dir}/jar" />

	<property name="main-class" value="ch.alexi.jdirsize.main.MainGui" />

	<path id="classpath">
	        <fileset id="libs" dir="${lib.dir}" includes="**/*.jar"/>
	</path>

	<target name="init">
		<mkdir dir="${classes.dir}"/>
		<mkdir dir="${lib.dir}"/>
		<mkdir dir="${jar.dir}"/>
	</target>

	<target name="clean" description="Removes build files">
		<echo>Cleaning up...</echo>
		<delete verbose="true">
			<fileset dir="${build.dir}"></fileset>
		</delete>
	</target>

	<target name="compile" depends="init">
		<javac srcdir="${src}" destdir="${classes.dir}"  classpathref="classpath" includeantruntime="false"></javac>
	</target>

  <target name ="makejar" depends="compile" description="Create a jar for the ${ant.project.name} project">
    <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
    	<fileset refid="libs"/>
    	<manifest>
    		<attribute name="Main-Class" value="${main-class}"/>
    	</manifest>
    </jar>
  </target>

	<target name="clean-build" depends="clean,makejar"/>

	<target name="run" depends="makejar">
	        <java jar="${jar.dir}/${ant.project.name}.jar" fork="true"/>
	</target>

	<target name="all" depends="clean,compile,makejar" description="Clean and Build whole project">
		<echo>Clean and build whole project</echo>
	</target>
</project>
Posted in techblog | Kommentare deaktiviert

Alternatives CSS-Stylesheet

Der angehängte Artikelbeschreibt, wie man alternative Stylesheets auf einer Seite anbietet und diese auch dynamisch wechselt:

Working With Alternate Style Sheets (PDF, 170kb)

Quelle: http://www.alistapart.com/articles/alternate/

Posted in techblog | Tagged , , | Kommentare deaktiviert

File-Dowload via Script in Internet Explorer

Der Internet Explorer hat mich heute aufs Neue fast in den Wahnsinn getrieben. Beim Ausliefern eines Datei-Downloads via Script (nicht durch relocate auf das eigentliche File) quittiert dies der Internet Explorer mit einer Fehlermeldung. Auch trotz geliefertem Content-Disposition-Header mit Filename versucht der IE, das Script-File downzuloaden.

Abhilfe schaffen die richtigen HTTP-Header, welche ich nach einigem Probieren gefunden habe. Das folgende kleine PHP-Snippet funktioniert so auf allen Browsern:

<code>header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"".$orig_filename."\"");
header("Pragma: "); // WICHTIG FUER IE
header("Cache-Control: "); // WICHTIG FUER IE
$fd = fopen ($fullPathToDonwloadFile, "r");
while(!feof($fd)) {
    $buffer = fread($fd, 2048);
    echo $buffer;
}</code>

Posted in techblog | Tagged , | Kommentare deaktiviert

Easing function demos

Ich habe eine kleine Sammlung von Easing-Functions für Animationen auf einer Demopage zusammengestellt:

http://www.alexi.ch/easing/

Easing-Functions-Demopage

Posted in techblog | Kommentare deaktiviert

Anti-Aliasing per Applikation abschalten

Um unter OS X das Anti-Aliasing per Applikation abzuschalten, genügt ein Eintrag im entsprechenden .plist-File, welches mittels dem “defaults”-Kommando gesetzt werden kann.

Als Beispiel hier in Aptana Studio 3:

defaults write com.aptana.studio3 AppleAntiAliasingThreshold 20

setzt den Threshold auf 20, was besagt, dass erst ab Schriftgrösse 20 Anti-aliasing verwendet wird. Den Domain-Namen findet man mittels ‘defaults domains’, oder im Verzeichnis ~/Library/Preferences/.

Danach sieht der Code-Editor so aus:

Posted in techblog | Tagged , | Kommentare deaktiviert

Color Clock

Color Clock ist ein kleines Farb-Experiment von mir: Es zeigt eine Seite mit der Tageszeit “entsprechenden” Hintergrundfarbe. Je nach Color Scheme werden die Farben des Spektrums anders gewechselt:

Vorschau auf die Color Clock-Page

http://www.alexi.ch/clock.html

Der Farbname wir dabei von der kleinen JavaScript-Library ‘Name That Color’ von Chirag  Mehta ermittelt.

Posted in techblog | Tagged , , , | Kommentare deaktiviert

Spielerischer Audio-Sequencer

Wer gerne Audio-Sequencer hat, hier ein spielerischer Ansatz: http://seaquence.org/

Posted in techblog | Tagged | Kommentare deaktiviert

PostgreSQL: ENUM-Typ anpassen

In PostgreSQL ist ein ENUM-Datentyp, einmal definiert, nur schwer anzupassen. Ein kleiner Eingriff ins Schema behebt dieses Problem aber:

INSERT INTO pg_enum(enumtypid,enumlabel)
VALUES(
(SELECT oid FROM pg_type WHERE typtype = 'e' AND typname = 'enum_typ_name'), 'neuer_wert'
);

Löschen allerdings ist heikler, da die Werte nicht mehr benutzt werden dürfen.

Posted in techblog | Tagged | Kommentare deaktiviert