Latest Entries »

Some days ago my new HC-SR04 ultrasonic sensor for my new Arduino board arrived. In order to keep the overview of my programs, I have written a small library for the sensor which I want to share with you here. As the library is pretty much self-explicatory in my opinion, I will not further comment the following code at this point.

UltraSonic.h

/*
  UltraSonic.h - A library for the HC-SR04 UltraSonic sensor.
  Created by Birk Blechschmidt, May 25, 2013.
  Released into the public domain.
*/

#ifndef UltraSonic_h
	#define UltraSonic_h

	#include "Arduino.h"

	class UltraSonic
	{
	  public:
		byte TriggerPin, DataPin;
		UltraSonic(byte TriggerPort, byte DataPort, unsigned int MaximumRange = 400);
		unsigned int ReadCentimeters();
		void ReadCentimetersAsync(int &Centimeters);
	  private:
		unsigned long AsyncTime;
		byte AsyncState;
		unsigned long AsyncLength;
		unsigned int Timeout;
	};

#endif

UltraSonic.cpp

/*
  UltraSonic.cpp - A library for the HC-SR04 UltraSonic sensor.
  Created by Birk Blechschmidt, May 25, 2013.
  Released into the public domain.
*/

#include "Arduino.h"
#include "UltraSonic.h"

UltraSonic::UltraSonic(byte TriggerPort, byte DataPort, unsigned int MaximumRange)
{
  Timeout = MaximumRange * 58;
  TriggerPin = TriggerPort;
  DataPin = DataPort;
  pinMode(TriggerPin, OUTPUT);
  digitalWrite(TriggerPin, LOW);
  pinMode(DataPin, INPUT);
  AsyncState = 0;
}

unsigned int UltraSonic::ReadCentimeters()
{
      digitalWrite(TriggerPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(TriggerPin, LOW);
      return pulseIn(DataPin, HIGH, Timeout)/58;
}

void UltraSonic::ReadCentimetersAsync(int &Centimeters)
{
  switch(AsyncState)
  {
    case 0:
    {
      Centimeters = -1;
      digitalWrite(TriggerPin, HIGH);
      AsyncTime = micros();
      AsyncState++;
      break;
    }
    case 1:
    {
      if(micros() >= AsyncTime + 10)
      {
        AsyncState++;
        digitalWrite(TriggerPin, LOW);
        AsyncTime = micros();
      }
      break;
    }
    case 2:
    {
      if(digitalRead(DataPin) == HIGH)
      {
        AsyncState++;
        AsyncTime = micros();
        
      }
      else if(micros() - AsyncTime > Timeout)
      {
        Centimeters = 0;
        AsyncState = 4; 
      }
      break;
    }
    case 3:
    {
      if(digitalRead(DataPin) == LOW)
      {
        Centimeters = (micros() - AsyncTime) / 58;
        AsyncState++;
      }
      else if(micros() - AsyncTime > Timeout)
      {
        Centimeters = 0;
        AsyncState++;
      }
      break;
    }
    case 4:
    {
      Centimeters = -1;
      AsyncState = 0;
      break;
    }
  }
}

Copy the above files to your Arduino libraries located at C:\Program Files\Arduino\libraries. Please be aware that you might need to create a new folder.

Alle Jahre wieder. So könnte das Motto für unsere Teilnahme beim saarländischen Robotik-
Wettbewerb „RoboNight“ lauten. Wie auch bereits in den vergangenen Jahren, hat unsere Schule
auch dieses Jahr wieder an dem von der Hochschule für Technik und Wirtschaft und T-Systems
gesponserten Wettbewerb teilgenommen. Dieses Mal traten wir zwar mit einer neuen Konstellation
an, dennoch wurde unsere Schule erfolgreich von unserem Team „Probots“ vertreten.
Wie jedes Jahr fanden an drei Samstagen Workshops in der HTW-Mensa statt. Dort galt es, diverse
Übungsaufgaben zu lösen. Aufgrund der vielen Teams, 25 mit insgesamt über 100 Schülern an der
Zahl, fand am 13. Oktober bereits ein Vorentscheid in der HTW statt, bei dem wir uns bereits als
erstes Team mit großem Abstand zum Zweitplatzierten qualifiziert haben.
Der Ablauf sah bei jeder dieser Veranstaltungen ähnlich aus. Zuerst wurde der Roboter aus den
verfügbaren Lego-Teilen zusammengebaut. (Diese umfassen unter anderem den programmierbaren
NXT-Stein, Licht-, Ultraschall- und Berührungssensoren sowie drei Motoren.) Danach wurde der
Roboter in NXC (Not eXactly C), einer Sprache mit C-ähnlicher Syntax, programmiert. Im Anschluss
wurden die geschriebenen Programme getestet und auf Fehler überprüft. Beim Vorentscheid sowie
im Finale wurde die Erfüllung der Aufgaben durch die Roboter schließlich noch präsentiert und mit
Punkten nach klaren Regeln bewertet.

Das Finale am 10. November begann bereits um 9.00 Uhr morgens in den Räumen der Telekom-
Tochter auf dem Eschberg. Nachdem wir in die Aufgabenstellungen eingeführt und in unsere
Arbeitsräume eingeteilt worden waren, konnten wir mit dem Programmieren loslegen. Wir mussten
bis 16.30 Uhr drei Aufgaben mit verschiedenen Schwierigkeiten bewältigen, welche wir ab etwa
19.30 Uhr präsentierten.
Die erste Aufgabe bestand im Folgen einer schwarzen Linie, was einfach durch die Erkennung des
Hell-Dunkel-Kontrasts mithilfe der Lichtsensoren zu realisieren war. Beim Folgen sollte der Roboter
an zwei markierten Punkten die Höhe von zwei verschiedenen, neben der Fahrbahn platzierten
Mauern messen und nach den Messungen die größere umstoßen. Zur Erkennung der Höhe nutzten
wir den Ultraschallsensor. Diese Aufgabe löste unser Roboter mit einer Bestzeit von knapp zehn
Sekunden und brachte uns somit 50 von 50 möglichen Punkten. Überraschend war, dass überhaupt
nur zwei Teams diese Aufgabe komplett lösen konnte.
Die zweite Aufgabe war schon etwas anspruchsvoller. Auf dem Spielfeld befanden sich drei parallele
schwarze Linien, wobei auf der vorderen Linie vier Blöcke positioniert waren. Eben dieser Grundlinie
sollte unser Roboter folgen, sobald er auf einen Block stieß, musste dieser weggeschoben werden.
Die Schwierigkeit bestand hier darin, dass der erste Block genau zwischen die beiden hinteren
Markierungen geschoben werden musste, der zweite hinter diese, der dritte wieder dazwischen und
der vierte erneut dahinter. Nach dem Verschieben der Blöcke musste der Roboter dann wieder zur
Grundlinie zurückkehren. Leider verschob unser Roboter beim zweiten Versuch nur drei der vier
Blöcke korrekt und kam dann aus ungeklärten Gründen nicht korrekt zurück auf die Grundlinie.
Daher erhielten wir für diese Aufgabe nur 30 Punkte, allerdings gab es auch hier nur zwei Roboter,
die den Parcours komplett bewältigten.
Bei der letzten und schwierigsten Aufgabe hatte sogar der Moderator Reinhard Karger vom DFKI
(Deutsches Forschungsinstitut für Künstliche Intelligenz) Probleme, diese mit der Hand zu lösen. Auf
drei Türmen war jeweils ein Ball positioniert, neben jedem Turm stand ein Korb, wobei jeder Korb
zusätzlich mit einer anderen Orientierung zur Grundlinie, auf welcher der Roboter sich bewegen
sollte, aufgestellt war. Mit sehr präzisem Geschick mussten die Bälle von den Türmen in die Körbe
gestoßen werden, jedoch ohne dabei den jeweiligen Turm umzuwerfen. Trotzdem passierte es
häufig, dass – aus Gründen der Ungenauigkeit oder wegen der federnden Wirkung des Materials –
der Ball einfach aus dem Korb heraushüpfte oder gar nicht erst hineinfiel. Daher schaffte auch Herr
Karger es nicht auf Anhieb, die Bälle mit der Hand in die Körbe zu stoßen. Beim ersten Versuch
meisterte unser Roboter als einziger diese Aufgabe mit ein wenig Glück komplett. Der komplette Saal
brach in Beifall aus und wir jubelten bereits, nachdem unser Roboter den ersten Ball in den
zugehörigen Korb befördert hatte, da dies bereits den Sieg für uns entschied. So erhielten wir mit 50
Punkten für diese Aufgabe erneut die höchstmögliche Punktzahl, was eine Gesamtpunktzahl von 130
Punkten ergab, und uns einen Vorsprung von insgesamt 47 Punkten vor der zweitplatzierten
Mannschaft verschaffte.

Nach einer mehr oder weniger kurzen Pause, in der wir unter anderem einem Reporter ein Interview
gaben, fand im Anschluss die Siegerehrung mitsamt der Preisverleihung und der symbolischen
Übergabe des Wanderpokals an unsere Schule statt. Da unsere Schule bereits 2011 den ersten Preis
mit meinem Team „RoboGuards” gewonnen hatte, wanderte der Pokal zu unserer Freude dieses Jahr ausnahmsweise
nicht.
Als glückliche Sieger erhielten wir beide die tragbare Spielekonsole „Nintendo 3DS“ und brachten
außerdem je einen Rucksack mit nach Hause – ganz zu schweigen von den tollen Erinnerungen und
Erfahrungen.

Preview RoboNight 2012
RoboNight 2012 — Der Vorentscheid
Review RoboNight 2012
Nachwuchs-Tüftler messen sich im Roboter-Kampf

Da ich für den Tag der offenen Tür meiner Schule, welcher bereits im Januar stattfand, eine etwas abwechslungsreichere und anspruchsvollere Projektidee gesucht habe, habe ich eine Abwandlung des 2D-Spiels “Helicopter” für den PC geschrieben, welche jedoch mit dem NXT gesteuert wird. Allerdings bin ich kein guter Grafiker, daher habe ich mein Spiel auf ein statisches Flugzeugbild beschränkt. Das gesamte Spiel wurde in C# programmiert, die Steuerung des NXTs in NXC.

Video:

Die NXT-Steuerung:
NXT-Steuerungsroboter

Quelltext C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace NXT_Helicopter
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        System.Drawing.Bitmap Bitmap;
        System.Drawing.Image plane;
        int planesize = 200;
        double planediagonal;
        bool started = false;
        Point screenmiddle;
        double rotation;
        int Byte;
        int oldByte=-1;
        Size Formsize;
        string path = "";
        long score = 0;
        long scoretoreach;

        ArrayList condensation;
        ArrayList highscorepoints;
        ArrayList highscorenames;
        TextBox nameBox;
        Button submitButton;

        ArrayList blocktypes;

        double leftfraction = (double)100 / 1000;

        double blockXfraction = (double)150 / (double)1000;
        double blockYfraction = (double)150 / (double)1000;

        double planefraction=(double)100 / (double)1000;

        ArrayList collisionZone;
        ArrayList originalZone;

        Color background = System.Drawing.Color.DeepSkyBlue;

        ArrayList blocks;
        

        Point planeposition;
        

        int maxData = 45;
        int maxDegrees = 45;

        double XSpeed = (double)10/(double)1000;
        double startspeed;

        double maxupfraction = (double)40/(double)1000;

        Point rotatePoint(Point middle, Point point, double degrees)
        {

            //return new Point((int)(middle.X + Math.Sin(degrees * Math.PI / 180) * Math.Sqrt(Math.Pow(point.X - middle.X, 2) + Math.Pow(point.Y - middle.Y, 2))), (int)(middle.Y + Math.Cos(degrees * Math.PI / 180) * Math.Sqrt(Math.Pow(point.X - middle.X, 2) + Math.Pow(point.Y - middle.Y, 2))));
            //return point;
            return new Point((int)(Math.Cos(degrees * Math.PI / 180) * (point.X - middle.X) - Math.Sin(degrees * Math.PI / 180)*(point.Y-middle.Y) + middle.X), (int)(Math.Sin(degrees * Math.PI / 180) * (point.X - middle.X) + Math.Cos(degrees * Math.PI / 180)*(point.Y-middle.Y) + middle.Y));
            //return new Point((int)(middle.X + Math.Cos(degrees * Math.PI / 180) * Math.Sqrt(Math.Pow(point.X - middle.X, 2) + Math.Pow(point.Y - middle.Y, 2))), (int)(middle.Y + Math.Sin(degrees * Math.PI / 180) * Math.Sqrt(Math.Pow(point.X - middle.X, 2) + Math.Pow(point.Y - middle.Y, 2))));
        }

        void nameBox_GotFocus(object sender, EventArgs e)
        {
            ((TextBox)sender).Text = "";
            ((TextBox)sender).ForeColor = Color.Black;
        }

        private void rotatePlane(double degrees)
        {
            double olddegrees=-degrees;
            degrees+=90;
            Point[] destinationPoints =
            {
                new Point((int)(planeposition.X+Math.Sin((degrees+135)*Math.PI/180)*(planediagonal)), (int)(planeposition.Y+Math.Cos((degrees+135)*Math.PI/180)*(planediagonal))),
                new Point((int)(planeposition.X+Math.Sin((degrees+45)*Math.PI/180)*(planediagonal)), (int)(planeposition.Y+Math.Cos((degrees+45)*Math.PI/180)*(planediagonal))),
                new Point((int)(planeposition.X+Math.Sin((degrees+225)*Math.PI/180)*(planediagonal)), (int)(planeposition.Y+Math.Cos((degrees+225)*Math.PI/180)*(planediagonal)))
            };
            Point middle = new Point((destinationPoints[0].X + destinationPoints[2].X) / 2, (destinationPoints[0].Y + destinationPoints[2].Y) / 2);
            middle = planeposition;
            for (int i = 0; i < originalZone.Count; i++)
            {
                Point pt = (Point)originalZone[i];

                collisionZone[i] = rotatePoint(middle, pt, olddegrees);
                
            }
            
            Graphics.FromImage(pictureBox1.Image).DrawImage(plane, destinationPoints);
            /*for (int i = 0; i < collisionZone.Count; i++)
            {
                Graphics.FromImage(pictureBox1.Image).FillRectangle(new SolidBrush(Color.Red), new Rectangle((Point)collisionZone[i], new Size(1, 1)));
            }*/
        }

        void updateScore()
        {
            tableLayoutPanel1.Controls.Clear();
            tableLayoutPanel1.RowCount = 0;
            tableLayoutPanel1.RowCount++;
            Label titlelabel = new Label();
            titlelabel.Name = "titlelabel";
            titlelabel.Text = "Highscore";
            titlelabel.Dock = DockStyle.Top;
            titlelabel.AutoSize = true;
            titlelabel.Font = new Font("Arial", 25, FontStyle.Bold);
            titlelabel.ForeColor = Color.Black;
            titlelabel.TextAlign = ContentAlignment.TopCenter;
            tableLayoutPanel1.Controls.Add(titlelabel, 0, 0);
            tableLayoutPanel1.SetColumnSpan(titlelabel, 2);
            tableLayoutPanel1.Visible = true;
            if (!System.IO.File.Exists(path + "highscore.txt"))
            {
                System.IO.File.WriteAllText(path + "highscore.txt", "");
            }
            string Highscore = System.IO.File.ReadAllText(path + "highscore.txt", Encoding.UTF8);
            string[] scores=Highscore.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < scores.Length; i++)
            {
                tableLayoutPanel1.RowCount++;
                for (int j = 0; j < 2; j++)
                {
                    Label label = new Label();
                    label.Text = scores[i].Split(new string[] { "\t" }, StringSplitOptions.None)[j];
                    label.AutoSize = true;
                    label.Dock = DockStyle.Top;
                    label.TextAlign = ContentAlignment.MiddleLeft;
                    label.Font = new Font("Arial", 20, FontStyle.Bold);
                    tableLayoutPanel1.Controls.Add(label, j, tableLayoutPanel1.RowCount-1);
                }
                highscorepoints.Add(Convert.ToInt64(scores[i].Split(new string[] { "\t" }, StringSplitOptions.None)[1]));
                highscorenames.Add(scores[i].Split(new string[] { "\t" }, StringSplitOptions.None)[0]);
            }
            nameBox = new TextBox();
            nameBox.Text = "Dein Name";
            nameBox.Dock = DockStyle.Bottom;
            nameBox.GotFocus += new EventHandler(nameBox_GotFocus);
            nameBox.ForeColor = Color.Gray;
            nameBox.Font = new Font("Arial", 20, FontStyle.Bold);
            Button replay = new Button();
            replay.Text = "Erneut spielen";
            replay.Dock = DockStyle.Bottom;
            replay.BackColor = SystemColors.ButtonFace;
            replay.AutoSize = true;
            replay.TextAlign = ContentAlignment.MiddleCenter;
            replay.Font = new Font("Arial", 20, FontStyle.Bold);
            replay.Click += new EventHandler(replay_Click);
            tableLayoutPanel1.RowCount++;
            tableLayoutPanel1.Controls.Add(nameBox, 0, tableLayoutPanel1.RowCount - 1);
            submitButton = new Button();
            submitButton.Text = "Eintragen";
            submitButton.AutoSize = true;
            submitButton.Font = new Font("Arial", 20, FontStyle.Bold); ;
            submitButton.Dock = DockStyle.Bottom;
            submitButton.TextAlign = ContentAlignment.MiddleCenter;
            submitButton.Click += new EventHandler(submitButton_Click);
            submitButton.BackColor = SystemColors.ButtonFace;
            tableLayoutPanel1.Controls.Add(submitButton, 1, tableLayoutPanel1.RowCount - 1);
            tableLayoutPanel1.RowCount++;
            tableLayoutPanel1.Controls.Add(replay, 0, tableLayoutPanel1.RowCount - 1);
            tableLayoutPanel1.SetColumnSpan(replay, 2);
        }

        void draw()
        {
            if (started)
            {
                bool collision = false;
                Image image = pictureBox1.Image;
                string debug = "Punktzahl: " + score.ToString();
                System.Random random = new Random();
                Graphics.FromImage(image).Clear(background);
                //Graphics.FromImage(pictureBox1.Image).DrawLine(new Pen(Color.Red), random.Next(pictureBox1.Width), random.Next(pictureBox1.Height), random.Next(pictureBox1.Width), random.Next(pictureBox1.Width));
                //Graphics.FromImage(pictureBox1.Image).DrawImage(plane, 10, 20, 150, 150);
                int Ychange=(int)(((double)Byte / (double)maxData) * (double)maxupfraction * (double)Formsize.Height);
                planeposition.Y -= Ychange;
                if (random.Next(30) == 5 && score >= scoretoreach)
                {
                    int top = random.Next(this.Height);
                    int width = random.Next(Formsize.Width / 100, Formsize.Width / 8);
                    int height = random.Next((int)((double)Formsize.Height * blockYfraction) + planesize + planesize / 3, this.Height - (int)((double)Formsize.Height * blockYfraction) - planesize - planesize / 3);
                    blocks.Add(new Rectangle(Formsize.Width, top, width, height));
                    blocktypes.Add((byte)1);
                    scoretoreach = score+ (long)((double)height / (double)25);
                }
                for (int i = 0; i < condensation.Count; i++)
                {
                    Point blockrect = (Point)condensation[i];
                    if (blockrect.X < -50)
                    {
                        condensation.RemoveAt(i);
                        i--;
                    }
                    else
                    {
                        blockrect.X -= (int)XSpeed;
                        condensation[i] = blockrect;
                    }
                }
                condensation.Add(new Point(planeposition.X, planeposition.Y));
                if (condensation.Count > 1)
                {
                    Graphics.FromImage(image).DrawCurve(new Pen(Color.FromArgb(150, Color.White), 10), (Point[])condensation.ToArray(typeof(Point)));
                }
                int left = 0;
                int downleft = 0;
                for (int i = 0; i < originalZone.Count; i++)
                {
                    Point pt = (Point)originalZone[i];
                    pt.Y -= Ychange;
                    originalZone[i] = pt;
                }
                for (int i = 0; i < blocks.Count; i++)
                {
                    Graphics.FromImage(image).FillRectangle(new SolidBrush(Color.LightGray), (Rectangle)blocks[i]);
                    Rectangle blockrect = (Rectangle)blocks[i];
                    if (blockrect.X + blockrect.Width < 0)
                    {
                        blocks.RemoveAt(i);
                        blocktypes.RemoveAt(i);
                        i--;
                    }
                    else
                    {
                        blockrect.X -= (int)XSpeed;
                        blocks[i] = blockrect;
                        if ((byte)blocktypes[i] == 0)
                        {
                            if (blockrect.X + blockrect.Width > left)
                            {
                                left = blockrect.X + blockrect.Width;
                            }
                        }
                        if ((byte)blocktypes[i] == 2)
                        {
                            if (blockrect.X + blockrect.Width > downleft)
                            {
                                downleft = blockrect.X + blockrect.Width;
                            }
                        }
                    }
                }
                while (left < Formsize.Width)
                {
                    int width = random.Next(20, (int)(blockXfraction * (double)Formsize.Width));
                    blocks.Add(new Rectangle(left, 0, width, random.Next((int)((double)Formsize.Height * blockYfraction) / 10, (int)((double)Formsize.Height * blockYfraction))));
                    blocktypes.Add((byte)0);
                    left += width;
                }
                while (downleft < Formsize.Width)
                {
                    int width = random.Next(20, (int)(blockXfraction * (double)Formsize.Width));
                    int height = random.Next((int)((double)Formsize.Height * blockYfraction) / 10, (int)((double)Formsize.Height * blockYfraction));
                    blocks.Add(new Rectangle(downleft, Formsize.Height-height, width, height));
                    blocktypes.Add((byte)2);
                    downleft += width;
                }
                rotatePlane(rotation);
                Graphics.FromImage(image).DrawString(debug, new System.Drawing.Font("Arial", 15), new SolidBrush(Color.Black), new Point(10, 10));
                pictureBox1.Refresh();
                for (int i = 0; i < blocks.Count; i++)
                {
                    Rectangle blockrect = (Rectangle)blocks[i];
                    for (int j = 0; j < collisionZone.Count; j++)
                    {
                        if (((Point)collisionZone[i]).X > blockrect.X && ((Point)collisionZone[i]).X < blockrect.X + blockrect.Width && ((Point)collisionZone[i]).Y > blockrect.Y && ((Point)collisionZone[i]).Y < blockrect.Y + blockrect.Height && !collision)
                        {
                            timer1.Stop();
                            collision = true;
                            System.Windows.Forms.Cursor.Show();
                            System.Windows.Forms.DialogResult result=MessageBox.Show("Du bist mit einem unbekannten Objekt kollidiert, dein Flugzeug ist nur noch Schrott.\n\nImmerhin hast du "+score.ToString()+" Punkte erreicht.\n\nMöchtest du dich in die Highscore eintragen?", "GAME OVER", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                            if (result == System.Windows.Forms.DialogResult.Yes)
                            {
                                
                                updateScore();
                                
                            }
                            else
                            {
                                load();
                            }
                        }
                    }
                }
                score++;
                if (score % 100 == 0)
                {
                    XSpeed = startspeed + score / 100;
                }
            }
        }

        void replay_Click(object sender, EventArgs e)
        {
            load();
        }

        void submitButton_Click(object sender, EventArgs e)
        {
            string highscorestring = "";
            bool inserted = false;
            for (int i = 0; i < highscorepoints.Count; i++)
            {
                if (score > (long)highscorepoints[i] && !inserted)
                {
                    highscorestring += nameBox.Text + "\t" + score.ToString() + "\r\n";
                    inserted = true;
                }
                highscorestring += (string)highscorenames[i] + "\t" + (long)highscorepoints[i] + "\r\n";
            }
            if (!inserted)
            {
                highscorestring += nameBox.Text + "\t" + score.ToString() + "\r\n";
                inserted = true;
            }
            System.IO.File.WriteAllText(path + "highscore.txt", highscorestring, Encoding.UTF8);
            updateScore();
            submitButton.Enabled=false;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            draw();
           
        }

        private void drawThread()
        {
            while (true)
            {
                draw();
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        }

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            while (serialPort1.BytesToRead >= 3)
            {
                serialPort1.ReadByte();
                serialPort1.ReadByte();
                oldByte=Byte+maxData;
                Byte=serialPort1.ReadByte();
                
                //MessageBox.Show(Byte.ToString());
                if (!started && Byte != oldByte)
                {
                    started = true;
                }
                Byte -= maxData;
                rotation = (double)(Byte * maxDegrees / (double)maxData);
                //rotation = Byte;
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            serialPort1.Dispose();
            serialPort1.Close();
        }

        void load()
        {
            highscorenames = new ArrayList();
            highscorepoints = new ArrayList();
            tableLayoutPanel1.Visible = false;
            score = 0;
            scoretoreach = 0;
            started = false;
            oldByte = -1;
            XSpeed = (double)10 / (double)1000;
            rotation = 0;
            this.BackColor = background;
            System.Windows.Forms.Cursor.Hide();
            blocktypes = new ArrayList();
            condensation = new ArrayList();
            blocks = new ArrayList();
            Formsize = this.Size;
            XSpeed *= Formsize.Width;
            screenmiddle = new Point((int)((double)Formsize.Width * leftfraction), Formsize.Height / 2);
            collisionZone = new ArrayList();
            originalZone = new ArrayList();
            planeposition = screenmiddle;
            plane = System.Drawing.Image.FromFile(path + "falcon.png");
            plane = plane.GetThumbnailImage((int)((double)Formsize.Width * planefraction), (int)((double)Formsize.Width * planefraction), null, IntPtr.Zero);
            planesize = plane.Width;
            planediagonal = Math.Sqrt((double)(planesize * planesize + planesize * planesize)) / (double)2;
            System.Drawing.Bitmap planeMap = new Bitmap(plane);
            Bitmap = new System.Drawing.Bitmap(pictureBox1.Width, pictureBox1.Height);
            pictureBox1.Image = Bitmap;
            for (int y = 0; y < plane.Height; y++)
            {
                for (int x = 0; x < plane.Width; x++)
                {
                    if (planeMap.GetPixel(x, y).A > 1 && planeMap.GetPixel(x, y).A < 255)
                    {
                        collisionZone.Add(new Point(screenmiddle.X - planesize / 2 + x, screenmiddle.Y - planesize / 2 + y));
                        originalZone.Add(new Point(screenmiddle.X - planesize / 2 + x, screenmiddle.Y - planesize / 2 + y));
                    }
                }
            }
            //originalZone = collisionZone;
            plane = planeMap;

            startspeed = XSpeed;
            timer1.Start();
            rotatePlane(0);
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            load();
            System.Windows.Forms.Cursor.Show();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            serialPort1.PortName = textBox1.Text;
            serialPort1.Open();
            System.Windows.Forms.Cursor.Hide();
            textBox1.Dispose();
            button1.Dispose();
        }
    }
}

Quelltext NXC

#define motor OUT_C
#define touch S4
#define BT 0

/*
Zuordnungen:
 45° -> 100%
  0° ->   0%
*/

byte buffer[1];
byte number;
int rotation;

int max=45;

task main()
{
   SetLongAbort(true);
   TextOut(0, LCD_LINE1, "Game Joystick");
   TextOut(0, LCD_LINE2, "(Motor C)");
   TextOut(0, LCD_LINE4, "Kalibrieren...");
   until(ButtonPressed(BTNCENTER, true));
   ResetRotationCount(motor);
   //PlayTone(440, 200);
   TextOut(0, LCD_LINE5, "OK");
   while(true)
   {
       rotation=MotorRotationCount(motor)%360;
       if(rotation > max)
       {
          rotation=max;
       }
       if(rotation < -max)
       {
          rotation=-max;
       }
       number=max+rotation;
       buffer[0]=number;
       BluetoothWrite(0, buffer);
       NumOut(0, LCD_LINE7, number);
       Wait(50);
   }
}

Downloads

Einfache, ausführbare Version oder Version mit Quelltext

Seit einiger Zeit verwende ich den Dienst Spambog.com, welcher Wegwerf-E-Mail-Adressen zur Verfügung stellt. Dort habe ich eine Sicherheitslücke entdeckt (XSS-Injection), die das Sperren fremder Konten möglich machte und dem Angreifer Zugriff zu passwortgeschützten Mailboxen verschaffen konnte. Nachdem die Sicherheitslücke mittlerweile behoben wurde, folgt hier ein Video mit näheren Informationen:

Da wir vor einiger Zeit im Informatikunterricht mit Backtracking-Algorithmen befasst und uns auch das Affenpuzzle angesehen haben, hatte ich mich entschlossen, ein kleines C++-Programm zu schreiben, welches selbiges löst.
Unter http://www.swisseduc.ch/informatik/120-lektionen/principles/computation/kara/docs/affenpuzzle_bastelbogen_unprotected.pdf kann man sich die Bastelvorlage des Affenpuzzles herunterladen.

Das Affenrätsel ist ein Puzzle, welches aus einem Quadrat aus mit einer bestimmten Kantenlänge (2, 3, 4, 5 oder mehr) Karten besteht. Jede Karte muss passend an die andere angelegt werden, sodass ein beispielsweise gelber Affenkopf nur an einem gelben Affenkörper anliegt. Dabei gibt es nur eine begrenzte Anzahl an Lösungen, welche ausschließlich durch ein sogenanntes Backtracking-Verfahren herauszufinden sind.

// Affenpuzzle.cpp: Birk Blechschmidt, 14 November 2011
// Dieser Kommentar muss erhalten bleiben.

#include "iostream"
#include "string"
#include "time.h"
using namespace std;

const char greenhead=1;
const char greenbody=2;
const char redhead=4;
const char redbody=5;
const char bluehead=7;
const char bluebody=8;
const char yellowhead=10;
const char yellowbody=11;
time_t beginning, ending;
double timespan;

long solutioncount=0;

long iterationcount=0;

const char rowcount=4;

const char fieldcount=rowcount*rowcount;
char cards[fieldcount][4];
char rotations[fieldcount];
char table[fieldcount];
bool set[fieldcount];
char* solutions=new char[0];

char modulus(char input)
{
	char output=input;
	if(output < 0)
	{
		output*=-1;
	}
	return output;
}

string getReadableName(char input)
{
	string name="";
	if(input==greenhead)
	{
		name="gh";
	}
	if(input==greenbody)
	{
		name="gb";
	}
	if(input==redhead)
	{
		name="rh";
	}
	if(input==redbody)
	{
		name="rb";
	}
	if(input==bluehead)
	{
		name="bh";
	}
	if(input==bluebody)
	{
		name="bb";
	}
	if(input==yellowhead)
	{
		name="yh";
	}
	if(input==yellowbody)
	{
		name="yb";
	}
	return name;
}

void rotateCard(char cardnumber, char rotationcount) //Uhrzeigersinn
{
	if(rotationcount !=0)
	{
		char tempCard[4];
		for(char i=0; i < 4; i++)
		{
			tempCard[i]=cards[cardnumber][i];
		}
		for(char i=0; i < 4; i++)
		{
			char newindex=i-rotationcount;
			while(newindex < 0)
			{
				newindex+=4;
			}
			while(newindex > 3)
			{
				newindex-=4;
			}
			cards[cardnumber][i]=tempCard[newindex];
		}
		rotations[cardnumber]+=rotationcount;
		while(rotations[cardnumber] < 0)
		{
			rotations[cardnumber]+=4;
		}
		while(rotations[cardnumber] > 3)
		{
			rotations[cardnumber]-=4;
		}
	}
}

bool validNeighbours(char cardnumber, bool debug=false)
{
	bool valid=true;
	if(cardnumber % rowcount > 0)
	{
		if(table[cardnumber-1]!=-1)
		{
			if(modulus(cards[table[cardnumber]][3]-cards[table[cardnumber-1]][1])!=1)
			{
				valid=false;
			}
		}
	}

	if(cardnumber % rowcount < rowcount-1)
	{
		if(modulus(cards[table[cardnumber]][1]-cards[table[cardnumber+1]][3])!=1)
		{
			if(table[cardnumber+1]!=-1)
			{
				valid=false;
			}
		}
	}

	if(cardnumber >= rowcount)
	{
		if(modulus(cards[table[cardnumber]][0]-cards[table[cardnumber-rowcount]][2])!=1)
		{
			if(table[cardnumber-rowcount]!=-1)
			{
				valid=false;
			}
		}
	}

	if(cardnumber < fieldcount-rowcount)
	{
		if(modulus(cards[table[cardnumber]][2]-cards[table[cardnumber+rowcount]][0])!=1)
		{
			if(table[cardnumber+rowcount]!=-1)
			{
				valid=false;
			}
		}
	}

	return valid;
}

void printCards()
{
	for(char yC=0; yC < rowcount; yC++)
	{
		for(char xC=0; xC < rowcount; xC++)
		{
			cout << " |";
			cout << getReadableName(cards[table[yC*rowcount+xC]][0]) << "| ";
		}
		cout << endl;
		for(char xC=0; xC < rowcount; xC++)
		{
			cout << getReadableName(cards[table[yC*rowcount+xC]][3]) << "| |";
			cout << getReadableName(cards[table[yC*rowcount+xC]][1]) <<" ";
		}
		cout << endl;
		for(char xC=0; xC < rowcount; xC++)
		{

			cout << " |";
			cout << getReadableName(cards[table[yC*rowcount+xC]][2]) << "| ";
		}
		cout << endl<<endl;
	}
}

void solve(char fieldnumber)
{
	for(char card=0; card < fieldcount; card++)
	{
		if(!set[card])
		{
			table[fieldnumber]=card;
			set[card]=true;
			for(char r=0; r<4; r++)
			{
				iterationcount++;
				if(validNeighbours(fieldnumber))
				{
					if(fieldnumber == fieldcount-1)
					{

						if(rotations[0]==0)
						{
							solutioncount++;
							cout << "Solution:"<<endl<<endl;
							char* temparr=new char[solutioncount*fieldcount*2];
							for(int i=0; i < solutioncount-1; i++)
							{
								for(int j=0; j < fieldcount; j++)
								{
									temparr[i*fieldcount*2+j*2]=solutions[i*fieldcount*2+j*2];
									temparr[i*fieldcount*2+j*2+1]=solutions[i*fieldcount*2+j*2+1];
								}
							}
							for(int i=0; i < fieldcount; i++)
							{
								temparr[(solutioncount-1)*fieldcount*2+i*2]=table[i];
								temparr[(solutioncount-1)*fieldcount*2+i*2+1]=rotations[table[i]];
							}
							solutions=new char[solutioncount*fieldcount*2];
							for(int i=0; i < solutioncount; i++)
							{
								for(int j=0; j < fieldcount; j++)
								{
									solutions[i*fieldcount*2+j*2]=temparr[i*fieldcount*2+j*2];
									solutions[i*fieldcount*2+j*2+1]=temparr[i*fieldcount*2+j*2+1];
								}
							}

								printCards();

							cout << endl<<endl;
						}
					}

					solve(fieldnumber+1);
				}
				rotateCard(card, 1);
			}
			table[fieldnumber]=-1;
			set[card]=false;
		}
	}
}

int main()
{

	//Kartendefinition 2*2
	/*cards[0][0]=greenbody;
 cards[0][1]=redhead;
 cards[0][2]=greenbody;
 cards[0][3]=bluehead;

 cards[1][0]=bluebody;
 cards[1][1]=greenhead;
 cards[1][2]=yellowhead;
 cards[1][3]=redbody;

 cards[2][0]=yellowbody;
 cards[2][1]=bluebody;
 cards[2][2]=redbody;
 cards[2][3]=bluehead;

 cards[3][0]=greenhead;
 cards[3][1]=bluebody;
 cards[3][2]=bluehead;
 cards[3][3]=yellowbody;*/

	//Kartendefinition 4*4
	cards[0][0]=redhead;
	cards[0][1]=bluehead;
	cards[0][2]=yellowhead;
	cards[0][3]=yellowhead;

	cards[1][0]=yellowbody;
	cards[1][1]=redhead;
	cards[1][2]=greenhead;
	cards[1][3]=redhead;

	cards[2][0]=redbody;
	cards[2][1]=bluehead;
	cards[2][2]=yellowbody;
	cards[2][3]=bluebody;

	cards[3][0]=bluebody;
	cards[3][1]=bluehead;
	cards[3][2]=yellowbody;
	cards[3][3]=greenhead;

	cards[4][0]=redbody;
	cards[4][1]=bluebody;
	cards[4][2]=greenhead;
	cards[4][3]=yellowhead;

	cards[5][0]=bluebody;
	cards[5][1]=redbody;
	cards[5][2]=bluehead;
	cards[5][3]=redbody;

	cards[6][0]=bluehead;
	cards[6][1]=bluehead;
	cards[6][2]=yellowbody;
	cards[6][3]=greenbody;

	cards[7][0]=redhead;
	cards[7][1]=greenhead;
	cards[7][2]=yellowhead;
	cards[7][3]=greenhead;

	cards[8][0]=redhead;
	cards[8][1]=greenbody;
	cards[8][2]=bluehead;
	cards[8][3]=greenbody;

	cards[9][0]=bluebody;
	cards[9][1]=greenhead;
	cards[9][2]=yellowbody;
	cards[9][3]=yellowbody;

	cards[10][0]=greenbody;
	cards[10][1]=bluehead;
	cards[10][2]=yellowhead;
	cards[10][3]=redbody;

	cards[11][0]=yellowbody;
	cards[11][1]=greenhead;
	cards[11][2]=greenbody;
	cards[11][3]=bluebody;

	cards[12][0]=greenbody;
	cards[12][1]=yellowhead;
	cards[12][2]=bluehead;
	cards[12][3]=bluehead;

	cards[13][0]=greenbody;
	cards[13][1]=yellowhead;
	cards[13][2]=redhead;
	cards[13][3]=redhead;

	cards[14][0]=yellowbody;
	cards[14][1]=greenhead;
	cards[14][2]=redhead;
	cards[14][3]=bluebody;

	cards[15][0]=redbody;
	cards[15][1]=yellowhead;
	cards[15][2]=redbody;
	cards[15][3]=greenhead;

	//Kartendefinition 6*6
	/*cards[0][0]=redbody;
 cards[0][1]=redhead;
 cards[0][2]=yellowhead;
 cards[0][3]=bluebody;

 cards[1][0]=redhead;
 cards[1][1]=redbody;
 cards[1][2]=yellowbody;
 cards[1][3]=bluehead;

 cards[2][0]=yellowhead;
 cards[2][1]=greenbody;
 cards[2][2]=greenbody;
 cards[2][3]=bluehead;

 cards[3][0]=greenhead;
 cards[3][1]=bluebody;
 cards[3][2]=yellowhead;
 cards[3][3]=yellowbody;

 cards[4][0]=redhead;
 cards[4][1]=greenhead;
 cards[4][2]=bluebody;
 cards[4][3]=bluebody;

 cards[5][0]=yellowhead,
 cards[5][1]=yellowhead;
 cards[5][2]=redbody;
 cards[5][3]=greenbody;

 cards[6][0]=redbody;
 cards[6][1]=redbody;
 cards[6][2]=redhead;
 cards[6][3]=bluehead;

 cards[7][0]=bluebody;
 cards[7][1]=redbody;
 cards[7][2]=redhead;
 cards[7][3]=bluehead;

 cards[8][0]=yellowbody;
 cards[8][1]=redhead;
 cards[8][2]=bluehead;
 cards[8][3]=greenbody;

 cards[9][0]=redhead;
 cards[9][1]=yellowbody;
 cards[9][2]=redhead;
 cards[9][3]=greenhead;

 cards[10][0]=bluehead;
 cards[10][1]=bluebody;
 cards[10][2]=redhead;
 cards[10][3]=redhead;

 cards[11][0]=greenhead;
 cards[11][1]=bluebody;
 cards[11][2]=bluebody;
 cards[11][3]=greenhead;

 cards[12][0]=greenhead;
 cards[12][1]=greenhead;
 cards[12][2]=bluehead;
 cards[12][3]=yellowbody;

 cards[13][0]=yellowbody;
 cards[13][1]=greenbody;
 cards[13][2]=redbody;
 cards[13][3]=greenbody;

 cards[14][0]=yellowhead;
 cards[14][1]=redhead;
 cards[14][2]=greenhead;
 cards[14][3]=bluebody;

 cards[15][0]=bluehead;
 cards[15][1]=yellowbody;
 cards[15][2]=greenbody;
 cards[15][3]=redhead;

 cards[16][0]=yellowbody;
 cards[16][1]=greenhead;
 cards[16][2]=redhead;
 cards[16][3]=redbody;

 cards[17][0]=yellowhead;
 cards[17][1]=bluehead;
 cards[17][2]=yellowhead;
 cards[17][3]=redhead;

 cards[18][0]=bluehead;
 cards[18][1]=bluebody;
 cards[18][2]=greenbody;
 cards[18][3]=greenhead;

 cards[19][0]=bluebody;
 cards[19][1]=yellowhead;
 cards[19][2]=greenhead;
 cards[19][3]=redhead;

 cards[20][0]=redbody;
 cards[20][1]=greenhead;
 cards[20][2]=yellowhead;
 cards[20][3]=bluebody;

 cards[21][0]=greenhead;
 cards[21][1]=greenhead;
 cards[21][2]=bluehead;
 cards[21][3]=redhead;

 cards[22][0]=redhead;
 cards[22][1]=redhead;
 cards[22][2]=bluebody;
 cards[22][3]=yellowhead;

 cards[23][0]=greenhead;
 cards[23][1]=yellowbody;
 cards[23][2]=redhead;
 cards[23][3]=yellowhead;

 cards[24][0]=redbody;
 cards[24][1]=yellowhead;
 cards[24][2]=bluehead;
 cards[24][3]=yellowbody;

 cards[25][0]=redhead;
 cards[25][1]=redbody;
 cards[25][2]=bluebody;
 cards[25][3]=bluehead;

 cards[26][0]=greenhead;
 cards[26][1]=redbody;
 cards[26][2]=yellowbody;
 cards[26][3]=yellowhead;

 cards[27][0]=greenbody;
 cards[27][1]=bluehead;
 cards[27][2]=greenhead;
 cards[27][3]=greenhead;

 cards[28][0]=bluehead;
 cards[28][1]=bluebody;
 cards[28][2]=bluehead;
 cards[28][3]=greenbody;

 cards[29][0]=yellowbody;
 cards[29][1]=bluehead;
 cards[29][2]=redbody;
 cards[29][3]=redbody;

 cards[30][0]=yellowhead;
 cards[30][1]=redbody;
 cards[30][2]=greenbody;
 cards[30][3]=redhead;

 cards[31][0]=redbody;
 cards[31][1]=bluehead;
 cards[31][2]=redbody;
 cards[31][3]=yellowhead;

 cards[32][0]=redhead;
 cards[32][1]=bluehead;
 cards[32][2]=yellowbody;
 cards[32][3]=yellowhead;

 cards[33][0]=bluehead;
 cards[33][1]=yellowhead;
 cards[33][2]=redhead;
 cards[33][3]=yellowbody;

 cards[34][0]=bluehead;
 cards[34][1]=yellowhead;
 cards[34][2]=yellowbody;
 cards[34][3]=redhead;

 cards[35][0]=greenbody;
 cards[35][1]=yellowhead;
 cards[35][2]=bluebody;
 cards[35][3]=bluehead;*/

	cout << "Monkey Puzzle Solver by Birk Blechschmidt, 14 November 2011"<<endl<<endl;
	cout << "Puzzle size: "<<(short)rowcount<<"*"<<(short)rowcount<<"="<<(short)fieldcount<<endl<<endl;
	cout << "Initial cards: "<<endl<<endl;
	for(int i=0; i < fieldcount; i++)
	{
		table[i]=i;
	}
	printCards();
	cout << endl<<endl;
	for(int i=0; i < fieldcount; i++)
	{
		rotations[i]=0;
		table[i]=-1;
		set[i]=false;
	}
	cout << "Press ENTER key to start..."<<endl<<endl;
	fflush(stdin);
	getchar();
	time(&beginning);
	solve(0);
	time(&ending);
	timespan=difftime(ending, beginning);
	cout << "In total "<<solutioncount<<" solutions were found in "<<timespan<<" seconds and "<<iterationcount<<" iterations."<<endl << endl;
	cout << endl << "Press ENTER key to quit..."<<endl<<endl;
	fflush(stdin);
	getchar();
	return 0;
}

Die Ausgabe:

Monkey Puzzle Solver by Birk Blechschmidt, 14 November 2011

Puzzle size: 4*4=16

Initial cards:

  |rh|      |yb|      |rb|      |bb|
yh|  |bh  rh|  |rh  bb|  |bh  gh|  |bh
  |yh|      |gh|      |yb|      |yb|

  |rb|      |bb|      |bh|      |rh|
yh|  |bb  rb|  |rb  gb|  |bh  gh|  |gh
  |gh|      |bh|      |yb|      |yh|

  |rh|      |bb|      |gb|      |yb|
gb|  |gb  yb|  |gh  rb|  |bh  bb|  |gh
  |bh|      |yb|      |yh|      |gb|

  |gb|      |gb|      |yb|      |rb|
bh|  |yh  rh|  |yh  bb|  |gh  gh|  |yh
  |bh|      |rh|      |rh|      |rb|

Press ENTER key to start...

Solution:

  |rh|      |gh|      |gh|      |gb|
yh|  |bh  bb|  |yb  yh|  |rh  rb|  |bh
  |yh|      |yb|      |gh|      |yh|

  |yb|      |yh|      |gb|      |yb|
rh|  |rh  rb|  |rb  rh|  |bh  bb|  |gh
  |gh|      |gh|      |gb|      |gb|

  |gb|      |gb|      |gh|      |gh|
bh|  |yh  yb|  |bh  bb|  |yh  yb|  |bb
  |bh|      |bh|      |rb|      |bh|

  |bb|      |bb|      |rh|      |bb|
yb|  |rb  rh|  |yb  yh|  |rh  rb|  |rb
  |bh|      |gh|      |gb|      |bh|

Solution:

  |rh|      |yb|      |bh|      |yb|
yh|  |bh  bb|  |gh  gb|  |bh  bb|  |gh
  |yh|      |rh|      |yb|      |gb|

  |yb|      |rb|      |yh|      |gh|
gh|  |yb  yh|  |bb  bh|  |rb  rh|  |yh
  |bb|      |gh|      |gb|      |gh|

  |bh|      |gb|      |gh|      |gb|
rb|  |rb  rh|  |yh  yb|  |bb  bh|  |rh
  |bb|      |rh|      |bh|      |gb|

  |bh|      |rb|      |bb|      |gh|
bh|  |gb  gh|  |yh  yb|  |rb  rh|  |rh
  |yh|      |rb|      |bh|      |yb|

Solution:

  |gh|      |yh|      |gb|      |rb|
rh|  |rh  rb|  |rb  rh|  |bh  bb|  |bh
  |yb|      |gh|      |gb|      |yb|

  |yh|      |gb|      |gh|      |yh|
bh|  |rb  rh|  |yh  yb|  |gb  gh|  |rb
  |gb|      |rh|      |bb|      |bb|

  |gh|      |rb|      |bh|      |bh|
yb|  |bb  bh|  |bb  bh|  |yb  yh|  |bh
  |bh|      |rb|      |gb|      |gb|

  |bb|      |rh|      |gh|      |gh|
rh|  |yb  yh|  |bh  bb|  |yb  yh|  |rh
  |gh|      |yh|      |yb|      |gh|

Solution:

  |rb|      |bh|      |rh|      |gh|
bb|  |bh  bb|  |yb  yh|  |bh  bb|  |yb
  |yb|      |gh|      |yh|      |yb|

  |yh|      |gb|      |yb|      |yh|
bh|  |rb  rh|  |bh  bb|  |gh  gb|  |bh
  |gb|      |gb|      |gb|      |bh|

  |gh|      |gh|      |gh|      |bb|
yh|  |rh  rb|  |rb  rh|  |rh  rb|  |rb
  |gh|      |yh|      |yb|      |bh|

  |gb|      |yb|      |yh|      |bb|
yb|  |bh  bb|  |gh  gb|  |rh  rb|  |gh
  |bh|      |rh|      |rh|      |yh|

Solution:

  |rb|      |gh|      |rh|      |bh|
bb|  |bh  bb|  |yb  yh|  |bh  bb|  |yb
  |yb|      |yb|      |yh|      |gh|

  |yh|      |yh|      |yb|      |gb|
gb|  |rh  rb|  |rb  rh|  |rh  rb|  |bh
  |rh|      |gh|      |gh|      |yh|

  |rb|      |gb|      |gb|      |yb|
yh|  |bb  bh|  |yh  yb|  |bh  bb|  |gh
  |gh|      |bh|      |bh|      |gb|

  |gb|      |bb|      |bb|      |gh|
bh|  |rh  rb|  |rb  rh|  |yb  yh|  |rh
  |gb|      |bh|      |gh|      |gh|

Solution:

  |yb|      |yb|      |bh|      |rh|
bh|  |bb  bh|  |gh  gb|  |gb  gh|  |gh
  |rb|      |bb|      |rh|      |yh|

  |rh|      |bh|      |rb|      |yb|
yb|  |gh  gb|  |bh  bb|  |bh  bb|  |gh
  |rh|      |yb|      |rb|      |rh|

  |rb|      |yh|      |rh|      |rb|
yh|  |bb  bh|  |rb  rh|  |gb  gh|  |yh
  |gh|      |gb|      |yh|      |rb|

  |gb|      |gh|      |yb|      |rh|
bh|  |yh  yb|  |gb  gh|  |yb  yh|  |bh
  |bh|      |bb|      |bb|      |yh|

Solution:

  |bh|      |rh|      |gh|      |gb|
rb|  |yb  yh|  |bh  bb|  |yh  yb|  |bh
  |bb|      |yh|      |rb|      |bh|

  |bh|      |yb|      |rh|      |bb|
bh|  |gb  gh|  |yb  yh|  |rh  rb|  |rb
  |yh|      |bb|      |gb|      |bh|

  |yb|      |bh|      |gh|      |bb|
bb|  |gh  gb|  |yh  yb|  |gb  gh|  |bh
  |rh|      |rb|      |bb|      |yb|

  |rb|      |rh|      |bh|      |yh|
gh|  |yh  yb|  |gh  gb|  |gb  gh|  |gh
  |rb|      |rh|      |rh|      |rh|

Solution:

  |bh|      |rh|      |rb|      |rb|
bb|  |yb  yh|  |bh  bb|  |bh  bb|  |bh
  |gh|      |yh|      |rb|      |yb|

  |gb|      |yb|      |rh|      |yh|
rb|  |bh  bb|  |gh  gb|  |gb  gh|  |gh
  |yh|      |gb|      |bh|      |rh|

  |yb|      |gh|      |bb|      |rb|
rh|  |rh  rb|  |rb  rh|  |yb  yh|  |bb
  |gh|      |yh|      |gh|      |gh|

  |gb|      |yb|      |gb|      |gb|
rh|  |yh  yb|  |bb  bh|  |yh  yb|  |bh
  |rh|      |gh|      |bh|      |bh|

Solution:

  |rh|      |rh|      |rb|      |rh|
gh|  |gh  gb|  |gb  gh|  |yh  yb|  |gh
  |yh|      |bh|      |rb|      |rh|

  |yb|      |bb|      |rh|      |rb|
bh|  |gh  gb|  |yb  yh|  |bh  bb|  |bh
  |bb|      |gh|      |yh|      |yb|

  |bh|      |gb|      |yb|      |yh|
rb|  |rb  rh|  |yh  yb|  |bb  bh|  |rb
  |bb|      |rh|      |gh|      |gb|

  |bh|      |rb|      |gb|      |gh|
bh|  |yb  yh|  |bb  bh|  |yh  yb|  |rh
  |gb|      |gh|      |bh|      |bb|

Solution:

  |rh|      |yh|      |gh|      |rh|
gh|  |gh  gb|  |bh  bb|  |yh  yb|  |gh
  |yh|      |bh|      |rb|      |rh|

  |yb|      |bb|      |rh|      |rb|
bh|  |gh  gb|  |yb  yh|  |bh  bb|  |bh
  |bb|      |gh|      |yh|      |yb|

  |bh|      |gb|      |yb|      |yh|
rb|  |rb  rh|  |bh  bb|  |gh  gb|  |rh
  |bb|      |gb|      |rh|      |rh|

  |bh|      |gh|      |rb|      |rb|
gb|  |bh  bb|  |yb  yh|  |gb  gh|  |yh
  |yb|      |yb|      |bh|      |rb|

Solution:

  |rh|      |yh|      |bh|      |bh|
gh|  |gh  gb|  |rh  rb|  |yb  yh|  |bh
  |yh|      |rh|      |bb|      |gb|

  |yb|      |rb|      |bh|      |gh|
gh|  |yb  yh|  |gh  gb|  |yh  yb|  |rh
  |bb|      |rb|      |rb|      |bb|

  |bh|      |rh|      |rh|      |bh|
gb|  |gb  gh|  |yb  yh|  |bh  bb|  |yb
  |rh|      |rh|      |yh|      |gh|

  |rb|      |rb|      |yb|      |gb|
yh|  |bb  bh|  |bb  bh|  |gb  gh|  |bb
  |gh|      |rb|      |bh|      |yb|

Solution:

  |gb|      |rb|      |gh|      |rh|
rh|  |bh  bb|  |bh  bb|  |yb  yh|  |bh
  |gb|      |rb|      |yb|      |yh|

  |gh|      |rh|      |yh|      |yb|
rb|  |rb  rh|  |gb  gh|  |rb  rh|  |rh
  |yh|      |yh|      |bb|      |gh|

  |yb|      |yb|      |bh|      |gb|
bh|  |bb  bh|  |gh  gb|  |yh  yb|  |bh
  |rb|      |bb|      |rb|      |bh|

  |rh|      |bh|      |rh|      |bb|
gh|  |bb  bh|  |gb  gh|  |gh  gb|  |yb
  |yb|      |yh|      |yh|      |gh|

Solution:

  |gh|      |rh|      |bh|      |rh|
bb|  |yb  yh|  |bh  bb|  |yb  yh|  |rh
  |yb|      |yh|      |gh|      |gb|

  |yh|      |yb|      |gb|      |gh|
rb|  |rb  rh|  |rh  rb|  |bh  bb|  |yh
  |gh|      |gh|      |yh|      |rb|

  |gb|      |gb|      |yb|      |rh|
bh|  |yh  yb|  |bh  bb|  |gh  gb|  |gb
  |bh|      |bh|      |gb|      |bh|

  |bb|      |bb|      |gh|      |bb|
yb|  |rb  rh|  |yb  yh|  |rh  rb|  |rb
  |bh|      |gh|      |gh|      |bh|

Solution:

  |rb|      |rh|      |rh|      |rb|
yh|  |gb  gh|  |yb  yh|  |bh  bb|  |bh
  |bh|      |rh|      |yh|      |yb|

  |bb|      |rb|      |yb|      |yh|
gh|  |bh  bb|  |bh  bb|  |gh  gb|  |bh
  |yb|      |rb|      |rh|      |bh|

  |yh|      |rh|      |rb|      |bb|
gh|  |rb  rh|  |gb  gh|  |yh  yb|  |gh
  |bb|      |yh|      |rb|      |yb|

  |bh|      |yb|      |rh|      |yh|
gb|  |bh  bb|  |gh  gb|  |gb  gh|  |gh
  |yb|      |gb|      |bh|      |rh|

Solution:

  |bh|      |yh|      |gb|      |yb|
bh|  |gb  gh|  |rb  rh|  |bh  bb|  |gh
  |yh|      |bb|      |gb|      |rh|

  |yb|      |bh|      |gh|      |rb|
bh|  |gh  gb|  |yh  yb|  |gb  gh|  |yh
  |bb|      |rb|      |bb|      |rb|

  |bh|      |rh|      |bh|      |rh|
bh|  |yb  yh|  |rh  rb|  |yb  yh|  |bh
  |gb|      |gb|      |bb|      |yh|

  |gh|      |gh|      |bh|      |yb|
bb|  |yb  yh|  |rh  rb|  |rb  rh|  |rh
  |yb|      |gh|      |bb|      |gh|

Solution:

  |bh|      |yh|      |bh|      |bb|
bh|  |gb  gh|  |gh  gb|  |yh  yb|  |gh
  |yh|      |rh|      |rb|      |yb|

  |yb|      |rb|      |rh|      |yh|
bh|  |gb  gh|  |yh  yb|  |gh  gb|  |rh
  |bh|      |rb|      |rh|      |rh|

  |bb|      |rh|      |rb|      |rb|
rh|  |yb  yh|  |bh  bb|  |bh  bb|  |bh
  |gh|      |yh|      |rb|      |yb|

  |gb|      |yb|      |rh|      |yh|
gh|  |bb  bh|  |gh  gb|  |gb  gh|  |rb
  |yb|      |bb|      |bh|      |bb|

Solution:

  |bh|      |rb|      |gh|      |rh|
yh|  |bh  bb|  |bh  bb|  |yb  yh|  |bh
  |gb|      |rb|      |yb|      |yh|

  |gh|      |rh|      |yh|      |yb|
rb|  |rb  rh|  |gb  gh|  |rb  rh|  |rh
  |yh|      |yh|      |bb|      |gh|

  |yb|      |yb|      |bh|      |gb|
bh|  |bb  bh|  |gh  gb|  |gb  gh|  |bb
  |rb|      |bb|      |rh|      |yb|

  |rh|      |bh|      |rb|      |yh|
gh|  |bb  bh|  |yb  yh|  |gb  gh|  |gh
  |yb|      |gb|      |bh|      |rh|

Solution:

  |rh|      |rb|      |gh|      |bh|
rh|  |gb  gh|  |yh  yb|  |rh  rb|  |yb
  |yh|      |rb|      |bb|      |bb|

  |yb|      |rh|      |bh|      |bh|
gh|  |yb  yh|  |bh  bb|  |yb  yh|  |bh
  |bb|      |yh|      |gh|      |gb|

  |bh|      |yb|      |gb|      |gh|
rb|  |rb  rh|  |rh  rb|  |bh  bb|  |yh
  |bb|      |gh|      |yh|      |rb|

  |bh|      |gb|      |yb|      |rh|
gb|  |gb  gh|  |bb  bh|  |gb  gh|  |gh
  |rh|      |yb|      |bh|      |yh|

Solution:

  |yb|      |rh|      |rh|      |rh|
bb|  |gh  gb|  |gb  gh|  |yb  yh|  |bh
  |rh|      |bh|      |rh|      |yh|

  |rb|      |bb|      |rb|      |yb|
yh|  |gb  gh|  |bh  bb|  |bh  bb|  |gh
  |bh|      |yb|      |yb|      |gb|

  |bb|      |yh|      |yh|      |gh|
rb|  |gh  gb|  |rh  rb|  |rb  rh|  |yh
  |yh|      |rh|      |gh|      |gh|

  |yb|      |rb|      |gb|      |gb|
yb|  |bb  bh|  |bb  bh|  |yh  yb|  |bh
  |gh|      |rb|      |bh|      |bh|

Solution:

  |rh|      |yb|      |bh|      |rh|
gh|  |bb  bh|  |gh  gb|  |yh  yb|  |gh
  |yb|      |bb|      |rb|      |rh|

  |yh|      |bh|      |rh|      |rb|
gb|  |rh  rb|  |yb  yh|  |bh  bb|  |bh
  |rh|      |bb|      |yh|      |rb|

  |rb|      |bh|      |yb|      |rh|
yh|  |gh  gb|  |bh  bb|  |gh  gb|  |gb
  |rb|      |yb|      |gb|      |bh|

  |rh|      |yh|      |gh|      |bb|
gh|  |gh  gb|  |bh  bb|  |yh  yb|  |gh
  |yh|      |bh|      |rb|      |yb|

Solution:

  |rh|      |yb|      |rb|      |rh|
gh|  |bb  bh|  |gb  gh|  |yh  yb|  |gh
  |yb|      |bh|      |rb|      |rh|

  |yh|      |bb|      |rh|      |rb|
gh|  |gh  gb|  |yb  yh|  |bh  bb|  |bh
  |rh|      |gh|      |yh|      |yb|

  |rb|      |gb|      |yb|      |yh|
yh|  |bb  bh|  |yh  yb|  |bb  bh|  |rb
  |gh|      |bh|      |gh|      |gb|

  |gb|      |bb|      |gb|      |gh|
bh|  |rh  rb|  |rb  rh|  |yh  yb|  |bb
  |gb|      |bh|      |rh|      |bh|

Solution:

  |gh|      |gb|      |bh|      |rh|
rb|  |rb  rh|  |bh  bb|  |yb  yh|  |bh
  |yh|      |gb|      |gh|      |yh|

  |yb|      |gh|      |gb|      |yb|
gh|  |yb  yh|  |rh  rb|  |bh  bb|  |gh
  |bb|      |gh|      |yh|      |rh|

  |bh|      |gb|      |yb|      |rb|
bh|  |gb  gh|  |bb  bh|  |bb  bh|  |bb
  |yh|      |yb|      |rb|      |rb|

  |yb|      |yh|      |rh|      |rh|
bh|  |gb  gh|  |rb  rh|  |gb  gh|  |yb
  |bh|      |bb|      |yh|      |rh|

Solution:

  |gh|      |rh|      |yb|      |rh|
rb|  |rb  rh|  |gb  gh|  |yb  yh|  |bh
  |yh|      |yh|      |bb|      |yh|

  |yb|      |yb|      |bh|      |yb|
bh|  |bb  bh|  |gh  gb|  |bh  bb|  |gh
  |rb|      |bb|      |yb|      |gb|

  |rh|      |bh|      |yh|      |gh|
gh|  |bb  bh|  |gb  gh|  |rb  rh|  |yh
  |yb|      |yh|      |bb|      |gh|

  |yh|      |yb|      |bh|      |gb|
bh|  |rb  rh|  |rh  rb|  |rb  rh|  |bh
  |gb|      |gh|      |bb|      |gb|

In total 23 solutions were found in 1 seconds and 26026288 iterations.

Press ENTER key to quit...

Mein Programm löst das Puzzle rekursiv, daher kann es zu Stapelüberläufen (Stackoverflows) kommen. Es empfiehlt sich daher das Heraufsetzen der maximalen Stapelgröße.

Heute war ich mal lyrisch aktiv und habe mir aufgrund der heutigen Demonstrationen folgendes Gedicht zusammengereimt zum Thema ACTA.

ACTA soll das Netz zensieren.
uns’re Freiheit limitieren.
Unser Will’ wird nicht erhört
und das Internet zerstört.

Megaupload ist schon weg,
Kinox soll noch nachzieh’n.
Nutzer, gezogen in den Dreck,
jetzt schon absolut verschrien.

Für Grooveshark, YouTube und auch Twitter
ist das Abkommen sehr bitter.
Denn für User, die es wagen,
geschützte Inhalte zu laden,
werden sie in Zukunft haften,
werden’s jedoch nicht verkraften.

An erster Stelle steht das Geld,
durch Internetdownloads geprellt.
Für die Online-Industrie
ist der Vertrag DIE Strategie.

Was ich allerdings nicht weiß:
Was soll überhaupt der [durch ACTA zensiert]?

Der Text darf gerne übernommen werden, er soll sogar weiterverbreitet werden. Gerne auch unter Angabe der Quelle ;)

Auch dieses Jahr haben wir wieder an der RoboNight teilgenommen, welche einmal jährlich von der Saarbrücker HTW (Hochschule für Technik und Wirtschaft) gemeinsam mit der Telekom-Tochter T-Systems veranstaltet wird. Bereits vorletztes und letztes Jahr nahmen wir an dem saarländischen Robotik-Wettbewerb teil, 2009 errichten wir den dritten Platz, letztes Jahr den zweiten. Gestern haben wir den ersten Preis gewonnen.

Bereits um 9.00 Uhr begann die RoboNight, nach einer Einführung in die Aufgaben und Regeln, konnten wir gegen 10.00 Uhr anfangen die LEGO Mindstorms NXT-Roboter zusammenzubauen und zu programmieren. Um 16:30 sollte Abgabeschluss sein, dieser wurde jedoch “völlig überraschend” um 20 Minuten verlängert. Wie jedes Jahr gab es drei Aufgaben, die zu bewältigen waren:

Die erste Aufgabe bestand darin, eine Zahlenfolge über Bluetooth zu empfangen und je nach Kombination entsprechende Schalter anzufahren. Bei optimaler Lösung waren 50 Punkte zu erreichen, wir haben nur 30 erreicht, da sich unser Roboter mit einem Zahnrad verfing und den letzten Schalter nicht betätigte. Auch die Zeit wurde bewertet. Der schnellste Roboter Roboter hat zehn Punkte bekommen, der zweite neun und so weiter, immer absteigend.

In der zweiten Aufgabe ging es um ein Umspannwerk, in dem man Hindernisse von einer Linie räumen und wieder darauf ablegen musste. Allerdings durfte dabei das angrenzende Hochspannungsfeld nicht vom Roboter befahren werden. Auch hier wurde die Zeit genau wie bei der ersten Aufgabe bewertet. Unser Roboter war ziemlich schnell und wir waren die Einzigen, die die Aufgabe vollständig lösen konnten und haben 50 oder 49 Punkte erreicht.

“Netzaufbau” war der Name der letzten Herausforderung, man musste an einer Linie entlangfahren und dreimal jeweils zur Rechten drei “Strommasten” (an Scharnieren befestigte, kleine Bretter mit Schnappmechanismus) aufstellen. Am Ende der Linie musste man einen Schalter betätigen, um eine Glühbirne (Symbol für das Land der Ideen) zum Leuchten zu bringen. Zu unserem Schrecken schlug unser erster Versuch fehl, jedoch klappte es beim zweiten Mal einwandfrei. Wie auch bei den anderen Aufgaben wurde auch hier die Zeit mit in die Bewertung einbezogen. Wir haben bei dieser Aufgabe 50 Punkte plus unsere Zeitpunkte erhalten.

Am Ende fand die die Preisverleihung mehr oder weniger spannend statt, denn bereits vor der Verleihung haben uns einige Leute zum bevorstehenden Sieg gratuliert, obwohl ich mir da doch noch nicht allzu sicher sein wollte. Knapp hinter uns auf dem zweiten Platz landeten “Die Relativen”, ein Team vom Albert-Einstein-Gymnasium in Völklingen.

Genauere Informationen befinden sich in der HTW-Online-Ausgabe Nr. 87 unter https://www.htw-saarland.de/organisation/htwonline/2011/87/9-t-systems-htw-robonight-in-saarbrucken-roboter-im-bereich-erneuerbarer-energien

Dear reader,

in this article I will show you how to write an application for downloading videos from the online platform YouTube using any programming language like C# .Net, JavaScript or any other language. I think this topic is quite interesting because I implemented a download function in my YouTube Gadget and I did not find any helpful resources on the internet.

Let’s imagine following situation: You found

a cool video on YouTube, now you want to download it (for playing it on your PC, mobile phone or iPod…).
What we do have is the URL of the YouTube interface similar to “http://www.youtube.com/watch?v=M1wbceaOwfg” containing the swf-file that plays our video.
What we do not have is the URL of the video file our browser is loading. I used Firebug, a useful extension for developers, to get the video file.

Firebug - Getting the video URL

As you can see, I activated the “Netzwerk/Network” module and selected “Flash” contents. You notice that the request which is shown is the request for the video because of the “Content-Type” field of the response header (“Antwort-Header”) which is set to “video/x-flv”, the mimetype of flv-flash-videos. If you copy the requested URL to the address bar of our browser,  a download dialog will be shown and ask you to open or save “videoplayback”. Well, if this file is opened with Adobe Media Player or any other program being able to play flv-videos, you will see that you can watch the downloaded video.

I think this is clear, but more interesting is to automate this process and to download/convert the videos to a more common format. Which mobile phone or iPod can play flv-files? So the next step to do is to search the source code of the YouTube video page for our urls. And – to put it in a nutshell – it can be found in the flashvars of the embed-tag or the object (using Firefox, YouTube’s sourcecode is using an embed-tag while YouTube’s sourcecode for Internet Explorer is using an object-tag).
And this is the quite long code my sourcecode contains:

<embed type="application/x-shockwave-flash"     src="http://s.ytimg.com/yt/swfbin/watch_as3-vfl3Eh29q.swf"     width="640" id="movie_player" height="390"    flashvars="fexp=903104%2C907702&amp;url_encoded_fmt_stream_map=url%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v11.lscache4.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Cratebypass%25252Ccp%2526fexp%253D903104%25252C907702%2526itag%253D43%2526ip%253D87.0.0.0%2526signature%253D30417352A65E14163FB6746AE6C6A871517A5FC9.0C91E36B690A5C885AAE0B7F43FE564444C00AD0%2526sver%253D3%2526ratebypass%253Dyes%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dmedium%26fallback_host%3Dtc.v11.cache4.c.youtube.com%26type%3Dvideo%252Fwebm%253B%2Bcodecs%253D%2522vp8.0%252C%2Bvorbis%2522%26itag%3D43%2Curl%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v21.lscache2.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Calgorithm%25252Cburst%25252Cfactor%25252Ccp%2526fexp%253D903104%25252C907702%2526algorithm%253Dthrottle-factor%2526itag%253D34%2526ip%253D87.0.0.0%2526burst%253D40%2526sver%253D3%2526signature%253DBC4BD5E7A48929985F533325AE046E5812B24D45.E599953DFB49361BD0CCDAE3A1FD06C4C7ED5A%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526factor%253D1.25%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dmedium%26fallback_host%3Dtc.v21.cache2.c.youtube.com%26type%3Dvideo%252Fx-flv%26itag%3D34%2Curl%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v22.lscache3.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Cratebypass%25252Ccp%2526fexp%253D903104%25252C907702%2526itag%253D18%2526ip%253D87.0.0.0%2526signature%253D81FDB64A4A19D55942C6C05CE4752A209C75C00D.D45F795019B8E8214EA20037660EF2B534C817F7%2526sver%253D3%2526ratebypass%253Dyes%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dmedium%26fallback_host%3Dtc.v22.cache3.c.youtube.com%26type%3Dvideo%252Fmp4%253B%2Bcodecs%253D%2522avc1.42001E%252C%2Bmp4a.40.2%2522%26itag%3D18%2Curl%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v22.lscache3.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Calgorithm%25252Cburst%25252Cfactor%25252Ccp%2526fexp%253D903104%25252C907702%2526algorithm%253Dthrottle-factor%2526itag%253D5%2526ip%253D87.0.0.0%2526burst%253D40%2526sver%253D3%2526signature%253DAB1BAAB6AEB36AA5449436B3B70DAEAC6CF4A309.BFF1F8A5C9179CF25B9121968EA70A0A31DE0088%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526factor%253D1.25%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dsmall%26fallback_host%3Dtc.v22.cache3.c.youtube.com%26type%3Dvideo%252Fx-flv%26itag%3D5&amp;enablecsi=1&amp;watermark=http%3A%2F%2Fs.ytimg.com%2Fyt%2Fswf%2Flogo-vfl_bP6ud.swf%2Chttp%3A%2F%2Fs.ytimg.com%2Fyt%2Fswf%2Fhdlogo-vfloR6wva.swf&amp;timestamp=1317576346&amp;plid=AASuVCYX1Hr0FlbH&amp;allow_embed=1&amp;watch_ajax_token=CzZGESebg7W8TR9XdtjYvm5lj4J8MTMxNzY2Mjc0NkAxMzE3NTc2MzQ2&amp;vq=auto&amp;showpopout=1&amp;autohide=2&amp;hl=en_US&amp;csi_page_type=watch5&amp;keywords=music%2Cyoutube%2Cgadget%2Cprogram%2Capp%2Capplication%2Csoftware%2Cwindows%2Cvista%2Cplayer%2Cplaylists%2Clisten%2Csidebar%2Cdesktop%2Cwidgets%2Centertainment%2Ccomputer&amp;cr=DE&amp;rvs=view_count%3D407%26author%3DRoboFan1406%26length_seconds%3D%2528104%252C%2529%26id%3D8q9RJ1wZQ5E%26title%3DLord%2Bof%2Bthe%2BRings%2B-%2BLord%2Bof%2Bthe%2BRings%2B-%2BShire%2BMusic%2Cview_count%3D162%26author%3DRoboFan1406%26length_seconds%3D%2528168%252C%2529%26id%3DyXnxYgUA2IA%26title%3DClimbing%2BNXT%2Cview_count%3D288%26author%3DRoboFan1406%26length_seconds%3D%2528109%252C%2529%26id%3DTRtIuqiBh50%26title%3DLEGO%2BMindstorms%2BNXT%2BGabelstapler%2Cview_count%3D4318143%26author%3DElektraRecords%26length_seconds%3D%2528257%252C%2529%26id%3Dfwr1hm_oBxE%26title%3DBruno%2BMars%2B-%2BIt%2BWill%2BRain%2B%255BNew%2BMusic%255D%2Cview_count%3D2724048%26author%3DkellyclarksonVEVO%26length_seconds%3D%2528235%252C%2529%26id%3D0C_oNMH0GTk%26title%3DKelly%2BClarkson%2B-%2BMr.%2BKnow%2BIt%2BAll%2Cview_count%3D2980984%26author%3DSMTOWN%26length_seconds%3D%2528203%252C%2529%26id%3DGvTaLTTanJc%26title%3DSuper%2BJunior%2B%25EC%258A%2588%25ED%258D%25BC%25EC%25A3%25BC%25EB%258B%2588%25EC%2596%25B4_A-CHA_Music%2BVideo%2Cview_count%3D1815682%26author%3DYourfavoritemartian%26length_seconds%3D%2528209%252C%2529%26id%3DTUmJDVRDRTQ%26title%3DWHIP%2BYO%2BKIDS%2Bfeaturing%2BNice%2BPeter%2Cview_count%3D953666%26author%3Drecklessswaggg%26length_seconds%3D%2528241%252C%2529%26id%3DPQocCi6j_mk%26title%3DHOW%2BTO%2BLOVE%2B%2528REMIX%2529%2B-%2BJUSTIN%2BBIEBER&amp;endscreen_module=http%3A%2F%2Fs.ytimg.com%2Fyt%2Fswfbin%2Fendscreen-vflNhEga_.swf&amp;fmt_list=43%2F320x240%2F99%2F0%2F0%2C34%2F320x240%2F9%2F0%2F115%2C18%2F320x240%2F9%2F0%2F115%2C5%2F320x240%2F7%2F0%2F0&amp;referrer=None&amp;user_gender=m&amp;logwatch=1&amp;length_seconds=25&amp;sendtmp=1&amp;enablejsapi=1&amp;sk=764YjHpjrC6O1ctvYaH35ppV7Bd9b6mnR&amp;theme=dark&amp;t=vjVQa1PpcFM-sb-PCui5mX1jKwIXdE1yWObSxWPQFp8%3D&amp;video_id=M1wbceaOwfg&amp;p_w=P-KpDhgwPVs&amp;tk=SVN8E4f4bLdCNRlCrLgJIJlnzby7tCDb5dJjT08JFAX6-DLCnnC5rQ%3D%3D&amp;user_age=33"     allowscriptaccess="always" allowfullscreen="true" bgcolor="#000000">

To make our flashvars more readable and accessible I decrypted the html-entities: (The following only shows the decoded flash parameters/flashvars, the other code is not too interesting.)

fexp=903104%2C907702
&url_encoded_fmt_stream_map=url%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v11.lscache4.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Cratebypass%25252Ccp%2526fexp%253D903104%25252C907702%2526itag%253D43%2526ip%253D87.0.0.0%2526signature%253D30417352A65E14163FB6746AE6C6A871517A5FC9.0C91E36B690A5C885AAE0B7F43FE564444C00AD0%2526sver%253D3%2526ratebypass%253Dyes%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dmedium%26fallback_host%3Dtc.v11.cache4.c.youtube.com%26type%3Dvideo%252Fwebm%253B%2Bcodecs%253D%2522vp8.0%252C%2Bvorbis%2522%26itag%3D43%2Curl%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v21.lscache2.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Calgorithm%25252Cburst%25252Cfactor%25252Ccp%2526fexp%253D903104%25252C907702%2526algorithm%253Dthrottle-factor%2526itag%253D34%2526ip%253D87.0.0.0%2526burst%253D40%2526sver%253D3%2526signature%253DBC4BD5E7A48929985F533325AE046E5812B24D45.E599953DFB49361BD0CCDAE3A1FD06C4C7ED5A%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526factor%253D1.25%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dmedium%26fallback_host%3Dtc.v21.cache2.c.youtube.com%26type%3Dvideo%252Fx-flv%26itag%3D34%2Curl%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v22.lscache3.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Cratebypass%25252Ccp%2526fexp%253D903104%25252C907702%2526itag%253D18%2526ip%253D87.0.0.0%2526signature%253D81FDB64A4A19D55942C6C05CE4752A209C75C00D.D45F795019B8E8214EA20037660EF2B534C817F7%2526sver%253D3%2526ratebypass%253Dyes%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dmedium%26fallback_host%3Dtc.v22.cache3.c.youtube.com%26type%3Dvideo%252Fmp4%253B%2Bcodecs%253D%2522avc1.42001E%252C%2Bmp4a.40.2%2522%26itag%3D18%2Curl%3Dhttp%253A%252F%252Fo-o.preferred.fra02s03.v22.lscache3.c.youtube.com%252Fvideoplayback%253Fsparams%253Did%25252Cexpire%25252Cip%25252Cipbits%25252Citag%25252Calgorithm%25252Cburst%25252Cfactor%25252Ccp%2526fexp%253D903104%25252C907702%2526algorithm%253Dthrottle-factor%2526itag%253D5%2526ip%253D87.0.0.0%2526burst%253D40%2526sver%253D3%2526signature%253DAB1BAAB6AEB36AA5449436B3B70DAEAC6CF4A309.BFF1F8A5C9179CF25B9121968EA70A0A31DE0088%2526expire%253D1317600000%2526key%253Dyt1%2526ipbits%253D8%2526factor%253D1.25%2526cp%253DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%2526id%253D335c1b71e68ec1f8%26quality%3Dsmall%26fallback_host%3Dtc.v22.cache3.c.youtube.com%26type%3Dvideo%252Fx-flv%26itag%3D5
&enablecsi=1
&watermark=http%3A%2F%2Fs.ytimg.com%2Fyt%2Fswf%2Flogo-vfl_bP6ud.swf%2Chttp%3A%2F%2Fs.ytimg.com%2Fyt%2Fswf%2Fhdlogo-vfloR6wva.swf
&timestamp=1317576346
&plid=AASuVCYX1Hr0FlbH
&allow_embed=1
&watch_ajax_token=CzZGESebg7W8TR9XdtjYvm5lj4J8MTMxNzY2Mjc0NkAxMzE3NTc2MzQ2
&vq=auto
&showpopout=1
&autohide=2
&hl=en_US
&csi_page_type=watch5
&keywords=music%2Cyoutube%2Cgadget%2Cprogram%2Capp%2Capplication%2Csoftware%2Cwindows%2Cvista%2Cplayer%2Cplaylists%2Clisten%2Csidebar%2Cdesktop%2Cwidgets%2Centertainment%2Ccomputer
&cr=DE
&rvs=view_count%3D407%26author%3DRoboFan1406%26length_seconds%3D%2528104%252C%2529%26id%3D8q9RJ1wZQ5E%26title%3DLord%2Bof%2Bthe%2BRings%2B-%2BLord%2Bof%2Bthe%2BRings%2B-%2BShire%2BMusic%2Cview_count%3D162%26author%3DRoboFan1406%26length_seconds%3D%2528168%252C%2529%26id%3DyXnxYgUA2IA%26title%3DClimbing%2BNXT%2Cview_count%3D288%26author%3DRoboFan1406%26length_seconds%3D%2528109%252C%2529%26id%3DTRtIuqiBh50%26title%3DLEGO%2BMindstorms%2BNXT%2BGabelstapler%2Cview_count%3D4318143%26author%3DElektraRecords%26length_seconds%3D%2528257%252C%2529%26id%3Dfwr1hm_oBxE%26title%3DBruno%2BMars%2B-%2BIt%2BWill%2BRain%2B%255BNew%2BMusic%255D%2Cview_count%3D2724048%26author%3DkellyclarksonVEVO%26length_seconds%3D%2528235%252C%2529%26id%3D0C_oNMH0GTk%26title%3DKelly%2BClarkson%2B-%2BMr.%2BKnow%2BIt%2BAll%2Cview_count%3D2980984%26author%3DSMTOWN%26length_seconds%3D%2528203%252C%2529%26id%3DGvTaLTTanJc%26title%3DSuper%2BJunior%2B%25EC%258A%2588%25ED%258D%25BC%25EC%25A3%25BC%25EB%258B%2588%25EC%2596%25B4_A-CHA_Music%2BVideo%2Cview_count%3D1815682%26author%3DYourfavoritemartian%26length_seconds%3D%2528209%252C%2529%26id%3DTUmJDVRDRTQ%26title%3DWHIP%2BYO%2BKIDS%2Bfeaturing%2BNice%2BPeter%2Cview_count%3D953666%26author%3Drecklessswaggg%26length_seconds%3D%2528241%252C%2529%26id%3DPQocCi6j_mk%26title%3DHOW%2BTO%2BLOVE%2B%2528REMIX%2529%2B-%2BJUSTIN%2BBIEBER
&endscreen_module=http%3A%2F%2Fs.ytimg.com%2Fyt%2Fswfbin%2Fendscreen-vflNhEga_.swf
&fmt_list=43%2F320x240%2F99%2F0%2F0%2C34%2F320x240%2F9%2F0%2F115%2C18%2F320x240%2F9%2F0%2F115%2C5%2F320x240%2F7%2F0%2F0
&referrer=None
&user_gender=m
&logwatch=1
&length_seconds=25
&sendtmp=1
&enablejsapi=1
&sk=764YjHpjrC6O1ctvYaH35ppV7Bd9b6mnR
&theme=dark
&t=vjVQa1PpcFM-sb-PCui5mX1jKwIXdE1yWObSxWPQFp8%3D
&video_id=M1wbceaOwfg
&p_w=P-KpDhgwPVs
&tk=SVN8E4f4bLdCNRlCrLgJIJlnzby7tCDb5dJjT08JFAX6-DLCnnC5rQ%3D%3D
&user_age=20

The information sent to the Shockwave flash video is pretty interesting. My gender and age… For us, the interesting parameter is “url_encoded_fmt_stream_map“. This parameter is URL-encoded, here it it decoded.

url=http%3A%2F%2Fo-o.preferred.fra02s03.v11.lscache4.c.youtube.com%2Fvideoplayback%3Fsparams%3Did%252Cexpire%252Cip%252Cipbits%252Citag%252Cratebypass%252Ccp%26fexp%3D903104%252C907702%26itag%3D43%26ip%3D87.0.0.0%26signature%3D30417352A65E14163FB6746AE6C6A871517A5FC9.0C91E36B690A5C885AAE0B7F43FE564444C00AD0%26sver%3D3%26ratebypass%3Dyes%26expire%3D1317600000%26key%3Dyt1%26ipbits%3D8%26cp%3DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%26id%3D335c1b71e68ec1f8&quality=medium&fallback_host=tc.v11.cache4.c.youtube.com&type=video%2Fwebm%3B+codecs%3D%22vp8.0%2C+vorbis%22&itag=43
,url=http%3A%2F%2Fo-o.preferred.fra02s03.v21.lscache2.c.youtube.com%2Fvideoplayback%3Fsparams%3Did%252Cexpire%252Cip%252Cipbits%252Citag%252Calgorithm%252Cburst%252Cfactor%252Ccp%26fexp%3D903104%252C907702%26algorithm%3Dthrottle-factor%26itag%3D34%26ip%3D87.0.0.0%26burst%3D40%26sver%3D3%26signature%3DBC4BD5E7A48929985F533325AE046E5812B24D45.E599953DFB49361BD0CCDAE3A1FD06C4C7ED5A%26expire%3D1317600000%26key%3Dyt1%26ipbits%3D8%26factor%3D1.25%26cp%3DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%26id%3D335c1b71e68ec1f8&quality=medium&fallback_host=tc.v21.cache2.c.youtube.com&type=video%2Fx-flv&itag=34
,url=http%3A%2F%2Fo-o.preferred.fra02s03.v22.lscache3.c.youtube.com%2Fvideoplayback%3Fsparams%3Did%252Cexpire%252Cip%252Cipbits%252Citag%252Cratebypass%252Ccp%26fexp%3D903104%252C907702%26itag%3D18%26ip%3D87.0.0.0%26signature%3D81FDB64A4A19D55942C6C05CE4752A209C75C00D.D45F795019B8E8214EA20037660EF2B534C817F7%26sver%3D3%26ratebypass%3Dyes%26expire%3D1317600000%26key%3Dyt1%26ipbits%3D8%26cp%3DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%26id%3D335c1b71e68ec1f8&quality=medium&fallback_host=tc.v22.cache3.c.youtube.com&type=video%2Fmp4%3B+codecs%3D%22avc1.42001E%2C+mp4a.40.2%22&itag=18
,url=http%3A%2F%2Fo-o.preferred.fra02s03.v22.lscache3.c.youtube.com%2Fvideoplayback%3Fsparams%3Did%252Cexpire%252Cip%252Cipbits%252Citag%252Calgorithm%252Cburst%252Cfactor%252Ccp%26fexp%3D903104%252C907702%26algorithm%3Dthrottle-factor%26itag%3D5%26ip%3D87.0.0.0%26burst%3D40%26sver%3D3%26signature%3DAB1BAAB6AEB36AA5449436B3B70DAEAC6CF4A309.BFF1F8A5C9179CF25B9121968EA70A0A31DE0088%26expire%3D1317600000%26key%3Dyt1%26ipbits%3D8%26factor%3D1.25%26cp%3DU0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4%26id%3D335c1b71e68ec1f8&quality=small&fallback_host=tc.v22.cache3.c.youtube.com&type=video%2Fx-flv&itag=5

Conspicious is that the parameter is not completely decoded, but the rest is very readable. All related parameter collections are separated by a comma, their parameters with values are separated by an “&”-character but the values are URL-encoded again – here is the completely decoded version:

url=http://o-o.preferred.fra02s03.v11.lscache4.c.youtube.com/videoplayback?sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Cratebypass%2Ccp
&fexp=903104%2C907702
&itag=43
&ip=87.0.0.0
&signature=30417352A65E14163FB6746AE6C6A871517A5FC9.0C91E36B690A5C885AAE0B7F43FE564444C00AD0
&sver=3
&ratebypass=yes
&expire=1317600000
&key=yt1
&ipbits=8
&cp=U0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4
&id=335c1b71e68ec1f8
&quality=medium
&fallback_host=tc.v11.cache4.c.youtube.com
&type=video/webm;+codecs="vp8.0,+vorbis"
&itag=43

,url=http://o-o.preferred.fra02s03.v21.lscache2.c.youtube.com/videoplayback?sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Calgorithm%2Cburst%2Cfactor%2Ccp
&fexp=903104%2C907702
&algorithm=throttle-factor
&itag=34
&ip=87.0.0.0
&burst=40
&sver=3
&signature=BC4BD5E7A48929985F533325AE046E5812B24D45.E599953DFB49361BD0CCDAE3A1FD06C4C7ED5A
&expire=1317600000
&key=yt1
&ipbits=8
&factor=1.25
&cp=U0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4
&id=335c1b71e68ec1f8
&quality=medium
&fallback_host=tc.v21.cache2.c.youtube.com
&type=video/x-flv
&itag=34

,url=http://o-o.preferred.fra02s03.v22.lscache3.c.youtube.com/videoplayback?sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Cratebypass%2Ccp
&fexp=903104%2C907702
&itag=18
&ip=87.0.0.0
&signature=81FDB64A4A19D55942C6C05CE4752A209C75C00D.D45F795019B8E8214EA20037660EF2B534C817F7
&sver=3
&ratebypass=yes
&expire=1317600000
&key=yt1
&ipbits=8
&cp=U0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4
&id=335c1b71e68ec1f8
&quality=medium
&fallback_host=tc.v22.cache3.c.youtube.com
&type=video/mp4;+codecs="avc1.42001E,+mp4a.40.2"
&itag=18

,url=http://o-o.preferred.fra02s03.v22.lscache3.c.youtube.com/videoplayback?sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Calgorithm%2Cburst%2Cfactor%2Ccp
&fexp=903104%2C907702
&algorithm=throttle-factor
&itag=5
&ip=87.0.0.0
&burst=40
&sver=3
&signature=AB1BAAB6AEB36AA5449436B3B70DAEAC6CF4A309.BFF1F8A5C9179CF25B9121968EA70A0A31DE0088
&expire=1317600000
&key=yt1
&ipbits=8
&factor=1.25
&cp=U0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4
&id=335c1b71e68ec1f8
&quality=small
&fallback_host=tc.v22.cache3.c.youtube.com
&type=video/x-flv
&itag=5

Now we have got our data. There are four possible downloads (withdrawable from the type-parameter):

  1. The first download is a WebM video (a video format developed by Google) with a medium quality.
  2. The second download is a flash video with medium quality.
  3. The third download is a mp4-video with medium quality.
  4. The fourth download is a flash video with small quality.

Please note that every whole paragraph displayed in the box above is one single video url, i. e. the download url for the first video type is:

http://o-o.preferred.fra02s03.v11.lscache4.c.youtube.com/videoplayback?sparams=id%2Cexpire%2Cip%2Cipbits%2Citag%2Cratebypass%2Ccp&fexp=903104%2C907702&itag=43&ip=87.0.0.0&signature=30417352A65E14163FB6746AE6C6A871517A5FC9.0C91E36B690A5C885AAE0B7F43FE564444C00AD0&sver=3&ratebypass=yes&expire=1317600000&key=yt1&ipbits=8&cp=U0hQTFZLTl9FSkNOMF9ORVJBOms0SXNQbnhxVEI4&id=335c1b71e68ec1f8&quality=medium&fallback_host=tc.v11.cache4.c.youtube.com&type=video/webm;+codecs="vp8.0,+vorbis"&itag=43

Now, to download this video, just download the file from this URL and you are done.

Note: It is not possible to demonstrate this function online because we need to send a request to YouTube first to retreive this URL. This is not possible because cross-domain-scripting (XSS) is not allowed by most common browsers.

In my YouTube Gadget I use the following code to download videos:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Video Downloader</title>
</head>
<body>
<h1>AJAX YouTube Video Downloader</h1>
<h2>Demo by <a href="http://robofan.de">robofan.de</a></h2>
<form onsubmit="javascript:DownloadFormats(document.getElementById('VideoURL').value); return false;">
<table cellspacing="3" border="0" cellpadding="0">
<tr><td>Video URL:</td><td><input type="text" id="VideoURL" style="width: 245px;" /></td></tr>
<tr><td>Video format:</td><td><select id="downloadformat" disabled="disabled" style="width: 250px;"><option>Enter the URL of a video first</option></select></td></tr>
<tr><td></td><td><input type="submit" value="Retreive video formats" id="downloadbutton" style="width: 250px;" /></td></tr>
</table>
</form>
<script type="text/javascript">
var Status=0;
function exactTags(text, start, end, number) //this function allows to retreive a string between to tags - example: 'tag("<tag>any text</tag>", "<tag>", "</tag>", 0);' returns "any text"
{
    var first=text.split(start);
    if(first.length > number+1)
    {
        var second=first[number+1];
        first=second.split(end);
        second=first[0];
        return second;
    }
    else
    {
        return "";
    }
}
function DownloadFormats(VideoURL)
{
    if(Status==0)
    {
        var FormatRequest = new ActiveXObject("Microsoft.XMLHTTP");
        FormatRequest.open("GET", VideoURL, true); //initialize request to retreive video URLs
        FormatRequest.onreadystatechange = function()
        {
            if(FormatRequest.readyState === 4)
            {
                if(FormatRequest.status === 200)
                {
                    document.getElementById("downloadformat").disabled=false;
                    document.getElementById("downloadformat").options.length=0;
                    document.getElementById("downloadbutton").value="Download/Show";
                    var DownloadData=decodeURIComponent(exactTags(exactTags(FormatRequest.responseText, '<param name="flashvars" value="', '"', 0), "url_encoded_fmt_stream_map=", "&", 0)).split(",");
                    for(i=0; i < DownloadData.length; i++)
                    {
                        if(decodeURIComponent(exactTags(DownloadData[i], "type=", "&", 0)).split(";")[0]!="video/webm") //If a video is not a Google WebM video
                        {
                            document.getElementById("downloadformat").options[document.getElementById("downloadformat").options.length]=new Option(decodeURIComponent(exactTags(DownloadData[i], "type=", "&", 0)).split(";")[0]+" ("+decodeURIComponent(exactTags(DownloadData[i], "quality=", "&", 0))+")", decodeURIComponent(exactTags(DownloadData[i], "url=", "&", 0))); //Annex the URL to a select-list
                           �
                        }
                    }
                    Status=1;
                }
            }
        }
        FormatRequest.send(null); //Send the request
    }
    else
    {
        window.open(document.getElementById("downloadformat").value);
        Status=0;
        document.getElementById("downloadbutton").value="Retreive video formats";
        document.getElementById("downloadformat").options.length=0;
        document.getElementById("downloadformat").options[0]=new Option("Select a video first");
        document.getElementById("downloadformat").disabled=true;
    }
}
</script>
This is a downloader for YouTube videos. Originally it was programmed for <a href="http://youtube.com">youtube-gadget.com</a>.
<p>Please note that you may - depending on your location - violate laws by downloading videos which are protected by copyright.<br/>The author does not take over responsibility for any kind of abuse of this function or these terms.</p>
</body>
</html>

This works fine for downloading any video except those which are not available in Germany. To use this function in your Internet Explorer (it will not work with other browsers) you can download the document here. (Right click -> Save as…) Please be aware that the document has to be stored in your local file system because otherwise cross domain requests to YouTube are not allowed and it will not work. For the same reason you should allow blocked running scripts or ActiveX controls.

After downloading a video you can several conversion tools to convert the videos to any format.

Thank you for reading this long article, I hope I could inspire you. Please comment.

Best Regards
Birk

Please note that you may – depending on your location – violate laws by downloading videos which are protected by copyright.
The author does not take over responsibility for any kind of abuse of this function or these terms.

My gadgets on gallery.live.com

My gadgets

Yesterday I was very shocked when I saw that Microsoft retired “gallery.live.com“. It has always been a suitable platform for submitting my gadgets which got more than 380,000 downloads (the rest of the counted 54,000 downloads came from a similar German Microsoft platform – apps.msn.de – which is luckily not offline – but new contents cannot be submitted either). Another point is that my “Gallery Gadget”, which searched for gadgets on the site, does not work anymore, users are now redirected to this page.
The page that is shown instead of the gadget platform shows following message:

The Windows Live Gallery has been retired. In order to focus support on the much richer set of opportunities available for the newest version of Windows, Microsoft is no longer supporting development or uploading of new Gadgets. However, some of the most popular and highest-rated gadgets are still available on the Gadgets page of the Windows Personalization Gallery.

With Windows Developer Preview, developers can create rich app experiences where customers focus on their important tasks. Apps are at the center of the Windows Developer Preview experience and are alive with activity and vibrant content. Users immerse themselves in your full-screen app while Windows gracefully gets out of the way.

Windows Developer Preview allows you to leverage your existing skills and code assets so you can create great experiences for your customers. Gadget and web developers can now use their HTML5 and CSS3 skills to build native Windows apps. .NET Developers can use XAML, C#, and Visual Basic to build beautiful Metro-style apps. Game developers can use the power of DirectX 11.1 to build amazing, immersive gaming experiences. Driver developers benefit from increased productivity with the new, integrated Visual Studio development environment.

(Source: gallery.live.com – October 1, 2011)

Note the third paragraph! Windows Vista and Windows 7 are both still available at the markets and they do not support gadgets anymore while XP is still supported?! Therefore I can now build metro apps for an operating system which has not even reached beta status.
Unfortunately I am not a big fan of the new metro style, I think metro style is more regress than progress. I do not want to use a computer which is not distinguishable from a mobile phone.

UPDATE (January 5, 2012):

If you are searching the gadgets which were available in the gadget gallery, you will find them all at gallery-live.com. Note the difference of the domain name, the new site contains a minus (“-”) which replaces the dot (“.”) in gallery.live.com. This service is operated by myself and not by Microsoft.

Some days ago I got a mail from a user who told me that my new YouTube Gadget could not be installed. This user got the following error: “This is not a valid gadget package.” First I thought it was en error because some files were not ready for archiving because the attribute for archiving was missing. I tried to zip the gadget completely but it did not work, neither with WinZip nor with WinRar. I read some topics on the internet but I did not found any solution. So I removed files from the archive step by step until it worked. The last file I removed was an empty file which was preserved for storing settings. So the problem was this empty file. Gadget Packages may not contain empty files or folders. I came to the result that I could create empty folders and files automatically with the file system object (FSO). Here you get some information on the MSDN: http://msdn.microsoft.com/en-us/library/z9ty6h50%28v=vs.85%29.aspx. I hope I could help you.