• Happy Coding

Archive for March, 2007

Picasa + iPhoto. I like it.

A nice combination which i now try to use to manage some of my photos: Picasa and the Picasa iPhoto-Plugin. A really smooth integration into Mac Os X.

OmniGraffle Stencils

Just found graffletopia.com. Contains a lot of cool and free stencils for OmniGraffle.

Second Life/Twitter Code

Second Life/Twitter application code available at the SL Developer’s Corner.

Twitter in Second Life

Just built a little Twitter / Second Life mashup using Ruby-on-Rails and LindenScript. Here is a little screenshot.

Twitterer in Second Life

I will put the code on my new SL-weblog at http://sl-devcorner.blogspot.com in this week :)

Rails 1.2.3

http://weblog.rubyonrails.org/2007/3/14/rails-1-2-3-compatible-with-ruby-1-8-6-and-other-fixes

Ruby 1.8.6

http://www.ruby-lang.org/en/news/2007/03/12/ruby-1-8-6-released/

TinyURL: Renaissance because of Twitter

Apparently the TinyURL-service experiences a renaissance because of Twitter. Nearly every URL in Twitter-messages is encoded via TinyURL. Nice.

The Effect of Stock Spam on Financial Markets

Passend zu einem der letzten Beiträge: “The Effect of Stock Spam on Financial Markets“.

Presentation screen for Second Life

I have built a small presentation screen with two navigation buttons. The whole communication between the buttons and the screen takes place using the llMessageLinked-function. Each slide have to be placed as texture into the prim of the mainscreen. The textures have to be numbered in the order in which they should be displayed later.

The script of the screen also informs the buttons when the last slide has been reached. So that the “next”-prim is not able to navigate anymore. The “previous” and “next” prim have nearly the same scriptcode, except that the one checks if the first slide has been reached and the other looks out for the last slide.

The lsl-code for the “previous” button looks like this.

integer slideToDisplay;

integer firstSlideReached;

integer currentSlide;default

{

    state_entry() {

        firstSlideReached = 1;

        slideToDisplay = 1;

        currentSlide = 1;

        llSetTexture("da79968e-b8b7-8a0a-cc66-2a717e9c3d41", 4);

        llRotateTexture(PI, 4);

    }

touch_start(integer total_number)

    {

        if(firstSlideReached == 0) {

            slideToDisplay = currentSlide - 1;

            llMessageLinked(LINK_SET,slideToDisplay,"slideToDisplay",NULL_KEY);

        } else {

            llSay(0, "First slide reached.");

        }

    }

link_message(integer sender_num, integer num, string str, key id) {

if(str == "currentSlide") {

            currentSlide = num;

            if(currentSlide == 1) {

                firstSlideReached = 1;

            } else {

                firstSlideReached = 0;

            }

         }

    }

}

The “next” prim code looks like this. It also uses a “arrow”-texture which is included via a key in the state_entry()-function. The “previous” button uses the same texture only rotated in another rotation.

integer slideToDisplay;

integer lastSlideReached;

integer currentSlide;

integer maxSlide;default

{

    state_entry() {

        lastSlideReached = 0;

        slideToDisplay = 1;

        currentSlide = 1;

        maxSlide = 1000;

        llSetTexture("da79968e-b8b7-8a0a-cc66-2a717e9c3d41", 4);

    }

touch_start(integer total_number)

    {

        if(lastSlideReached == 0) {

            slideToDisplay = currentSlide + 1;

            llMessageLinked(LINK_SET,slideToDisplay,"slideToDisplay",NULL_KEY);

        } else {

            llSay(0, "Last slide reached.");

        }

    }

link_message(integer sender_num, integer num, string str, key id) {

if(str == "currentSlide") {

            currentSlide = num;

            if(currentSlide < maxSlide) {

                lastSlideReached = 0;

            }

         }

if(str == "lastSlideReached" && num == 1) {

            lastSlideReached = 1;

            maxSlide = currentSlide;

    	}

 }

}

The screen itself checks first if a texture is available. If not it sets an test-texture (in this case: some color-circles i did, identified by the unique-key).

integer lastSlideReached;

integer firstSlideReached;

integer currentSlide;default {

state_entry() {

        // check for first slide and set it when available

        if(llGetInventoryKey("1") != NULL_KEY) {

            llSetTexture("1", 4);

        } else {

            llSetTexture("b13e131e-13a4-37ad-e137-4b6f81a0a3fa", 4);

        }

    }

link_message(integer sender_num, integer num, string str, key id) {

if(str == "slideToDisplay") {

            string slideToDisplayStr = (string) num;

if(llGetInventoryKey(slideToDisplayStr) != NULL_KEY) {

                llSetTexture((string)num, 4);

                llMessageLinked(LINK_SET,num,"currentSlide",NULL_KEY);

// check if next slide exists

                integer nextSlideNr = num+1;

                string nextSlideStr = (string) nextSlideNr;

                //llSay(0, "check for next slide nr " + nextSlideStr);

                if(llGetInventoryKey(nextSlideStr) == NULL_KEY) {

                    lastSlideReached = 1;

                    llMessageLinked(LINK_SET,1,"lastSlideReached",NULL_KEY);

                } else {

                    lastSlideReached = 0;

                }

             } else {

                llSay(0, "Slide not available");

            }

        }

    }

}

With some text-textures the screen will look like this:

Presentation screen

On the left side is the test-texture i did, if no slides are available.

To see it live in SL visit the “SL Developer’s Corner“.

Aktienkauf-Spam

In letzter Zeit bekomme ich immer mehr Spam-E-Mails, die mir den Kauf von Aktien empfehlen. Und mir ist mal aufgefallen, dass es anscheinend immer einige Leute gibt, die auf diese unseriösen Kaufempfehlungen reinfallen und dadurch den Kurs der Aktie dann doch erheblich nach oben manipulieren.

Zum Beispiel dümpelte der letzte “Tipp” im Bereich von 0,05 – 0,07 Euro rum. Zu diesem Kurs wurde natürlich dann vom “geheimnisvollen Tipp-Geber” gekauft. Anfang März gingen dann die Spam-Mails raus und siehe da: Ein Kurssprung von über 100% in den zweistelligen Cent-Bereich! Wohlgemerkt innerhalb von 2 Tagen!

Verlierer in diesem Spiel sind natürlich erstens das Unternehmen, dass zum Spielball wird und dessen Kurs nach kurzer Zeit wieder ordentlich in den Keller geht, zweitens die wirklichen Anleger, die verunsichert sind und drittens die Spam-Käufer, die nicht rechtzeitig den Absprung schaffen.

Aber wenn diese Spam-Mails anscheinend doch so großen Einfluss auf Kursverläufe haben, wäre es doch mal überlegenswert, ob man diese Informationen nicht in die Unternehmensmeldungen mit aufnimmt. Dann stehen neben den normalen Nachrichten wie “Kapitalerhöhung”, “Absatzzahlen” usw. dann ebenfalls Meldungen in der Art “Heute gingen 10.000.000 Spam-Mails raus. Die Aktie schloss dadurch mit einem Plus von 400%.” ;)

Linden Script @ Dr. Dobb’s

Nice Linden Script introduction at the Dr. Dobb’s site.

Display external XML-Resources on objects in Second Life

If have played a little bit with Second Life and its ability to access external resources. Inspired by Matt Biddulph’s “flickr screen”, now i wanted to load xml data from an external source into the SL-world and display it on a nice looking screen. Because it is not possible — from my point of view — to display text directly on a SL-primitive, it was necessary to render the text in a first step to an image. I did this using a little RubyOnRails application which also loads and parses the xml-resource. Ok, now i show how i did this.
I used the REXML processor to work with the xml-data and RMagick to create the image. The xml-source is used is a little xml-file provided by LindenLabs which shows the land sales by resident for the last three month (http://secondlife.com/reports/marketplace_stats/2007-03-01/land_sales_by_residents.xml). The whole parsing is specific to this source.

# get the xml via http and read it into a variable and create a XML-Document after that
@content = Net::HTTP.get(URI.parse("
http://secondlife.com/reports/marketplace_stats/2007-03-01/land_sales_by_residents.xml"))
xmlDoc = REXML::Document.new(@content)

# get some attributes and select them with xpath
elRecords = REXML::XPath.first(xmlDoc, "records")
reportTitle = elRecords.attributes['report']
reportDate = elRecords.attributes['date']

# create a new image in the size you need. in my case it was 400 width and 200 height
f = Image.new(400,200) { self.background_color = "white" }# make some settings for the font
drawable = Magick::Draw.new
drawable.pointsize = 15.0
drawable.font_family = 'Helvetica'
drawable.fill = 'gray'
drawable.gravity = Magick::NorthWestGravity
drawable.font_weight = Magick::BoldWeight
drawable.annotate(f, 0, 0, 5, 4, "Second Life #{reportTitle} (#{reportDate})")
drawable.pointsize = 13.0
drawable.fill = 'black'
drawable.font_weight = Magick::NormalWeight

# set some position for the text i want to print
@startTopPos = 24

# go the records in the xml-document and print the values into the new image
REXML::XPath.each( xmlDoc, "records/record") do |element|
	element.elements.each("field") do |field|
		name = field.attributes['name']
		value = field.attributes['value']
		drawable.annotate(f, 0, 0, 5, @startTopPos, name)
		drawable.annotate(f, 0, 0, 250, @startTopPos, value)
		@startTopPos = @startTopPos + 15
	end
	@startTopPos = @startTopPos + 15
end

# write the image to the disk. i wasnt able to return it directly without saving. :(
f.write("result.png")
# return the image
createdImg = Magick::Image.read("result.png").first
@response.headers["Content-Type"] = "image/png"
@response.headers['Content-Disposition'] = %q{inline; filename="thepicture.png"}
render :text => createdImg.to_blob

This script returns the following image:

Second Life land sales

To put this image on an primitive i used the following linden script code:

touch_start(integer num_detected) {
    llSay(0, "trying..."); 

    if(llGetLandOwnerAt(llGetPos()) != llGetOwner()) {
        llSay(0,"Error: Cannot modify parcel media settings.");
    } 

    key video_texture = llList2Key(llParcelMediaQuery( [PARCEL_MEDIA_COMMAND_TEXTURE]), 0);

    if(video_texture == NULL_KEY)
    {
        video_texture = VIDEO_DEFAULT;
        llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_TEXTURE, VIDEO_DEFAULT]);
    }
    llSetTexture(video_texture,ALL_SIDES);
    llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_URL,"http://###URL###"]);
    llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_PLAY]);
    llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AUTO_ALIGN,TRUE]);
}

###URL### has to be replaced with the URL of the Ruby-Script.

Note: To use this ParcelMedia-feature you have to allow streaming media i think in SL.

Und da springen sie wieder

Und zwar auf den Trend-Zug “SecondLife” auf — die Gebrüder Samwer. Jetzt haben die anscheinend einen Anteil an den “Anshe Chung Studios”, dem SecondLife-Grundstücksunternehmen von Ailin Graef, erworben. Vom Ruf her passen die beiden natürlich gut zusammen. ;)

FAZ: Die Brüder Alexander, Marc und Oliver Samwer haben sich über ihre Beteiligungsgesellschaft European Founders mit 10 Prozent an den Anshe Chung Studios beteiligt, dem Unternehmen der ersten Second-Life-Millionärin Ailin Gräf.