<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://soapitstop.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">.NET Flea Market</title><subtitle type="html" /><id>http://soapitstop.com/blogs/fleamarket/atom.aspx</id><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/default.aspx" /><link rel="self" type="application/atom+xml" href="http://soapitstop.com/blogs/fleamarket/atom.aspx" /><generator uri="http://communityserver.org" version="3.0.20611.960">Community Server</generator><updated>2008-02-20T00:57:00Z</updated><entry><title>Questions; Twenty of 'em</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/08/12/questions-twenty-of-em.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/08/12/questions-twenty-of-em.aspx</id><published>2008-08-12T01:41:02Z</published><updated>2008-08-12T01:41:02Z</updated><content type="html">&lt;p&gt;I was thinking of that interesting little pocket game, 20Q, where the game knows so many words and is able to figure out what word you&amp;#39;re thinking of in 20 questions.&amp;#160; For the most part, it&amp;#39;s not too bad.&amp;#160; It must really be pretty complex to be able to figure out all those words.&lt;/p&gt;  &lt;p&gt;I&amp;#39;ve brainstormed on this idea before and whenever I start the code for it, I lose interest, but it doesn&amp;#39;t stop me from kicking it around in my head over and over.&lt;/p&gt;  &lt;p&gt;So pretty much, you have a database table full of answer words, which also has a numeric PK, you have a table of questions, with numeric PK, and you have a table with a matrix of every question and every answer PK and a response value (1=yes, 0=no).&amp;#160; That would be the basic data structure.&amp;#160; For data population, you could fill the answer table with random nouns pulled from any dictionary file.&amp;#160; That&amp;#39;s simple.&amp;#160; For the questions table, you&amp;#39;d have to enter as many random questions as you could think of.&amp;#160; Random.&amp;#160; And LOTS.&amp;#160; Don&amp;#39;t think of the answer, just think of any question.&amp;#160; Then after you&amp;#39;ve fried your mind with questions, do a Cartesian join to insert the PKs into the matrix table, leaving the response field null.&amp;#160; Now the fun part.&amp;#160; Make a form with big Yes and No buttons.&amp;#160; The form will read each row in the matrix table, joined with the question and answer table and you respond yes or no to each question/answer combination.&amp;#160; This should take a few days.&lt;/p&gt;  &lt;p&gt;After sleeping off that headache and letting your eyes reset, it would be time to test coverage.&amp;#160; Do all of your questions provide a unique combination for every answer?&amp;#160; Does that get the wheels in your head spinning as to how to create such a uniqueness test?&amp;#160; I&amp;#39;m going to post my untested first idea, because nothing spurs responses better than posting something wrong.&amp;#160; My idea would be have an outer query (this is in .NET) for each answer PK, then an inner query that reads the question PK for each response that is yes (sorted by question PK, filtered by answer PK), loop through the inner query and concatenate the question PKs together into a big string and store it (maybe in a hashtable) with the answer ID as the value.&amp;#160; If you hit a dupe, then you have two answers that have the exact same yes responses.&lt;/p&gt;  &lt;p&gt;After you&amp;#39;ve tested for full coverage and removed any answers that can&amp;#39;t be exclusively answered by a series of responses, the goal is to present the most efficient question first.&amp;#160; What is the most efficient question?&amp;#160; The one that removes the most answers from the potential answer pool.&amp;#160; This is another fun mental exercise.&amp;#160; At the simplest level, it&amp;#39;s the count of answers grouped by question filtered by all previous questions that don&amp;#39;t match previous responses.&amp;#160; Something like (in pseudo-code)&lt;/p&gt;  &lt;p&gt;select Questions.ID,count(Answers.ID) AnswerCount   &lt;br /&gt;from QAMatrix    &lt;br /&gt;join Answers on QAMatrix.AnswersID=Answers.ID    &lt;br /&gt;join Questions on QAMatrix.QuestionsID=Questions.ID    &lt;br /&gt;where Questions.ID=[previous question id] and QAMatrix.Response&amp;lt;&amp;gt;[previous response value]    &lt;br /&gt;and Questions.ID=[previous question id] and QAMatrix.Response&amp;lt;&amp;gt;[previous response value]    &lt;br /&gt;...    &lt;br /&gt;group by Questions.ID    &lt;br /&gt;order by 2 desc&lt;/p&gt;  &lt;p&gt;I think that would do it.&amp;#160; The first question in the results should have the highest answers being trimmed out.&amp;#160; Looking at it now during a proofread, I suppose it might need enhanced so that it identifies the balance of yes/no responses in that count.&amp;#160; It won&amp;#39;t do much good if 90% the answers were yes.&amp;#160; Well... depending on the answer, that&amp;#39;s a potential risk with a potential huge reward - wiping out 90% of the possible answers.&amp;#160; Would an advanced 20Q program take more risks early or later or would it play middle-of-the-road and always shoot for a 50% split?&amp;#160; Design details for the interested.&amp;#160; Another 2nd version detail might be to remove any questions that don&amp;#39;t split the answers well enough.&amp;#160; Maybe that&amp;#39;s how 20Q ended up with such weird questions like &amp;quot;Does it grow hair?&amp;quot;&lt;/p&gt;  &lt;p&gt;And that&amp;#39;s about all the fun stuff I&amp;#39;ve been thinking about and not doing lately.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=253" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry><entry><title>A Totally Non-Random Post</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/06/25/a-totally-non-random-post.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/06/25/a-totally-non-random-post.aspx</id><published>2008-06-26T00:42:10Z</published><updated>2008-06-26T00:42:10Z</updated><content type="html">&lt;p&gt;I am sure this is covered somewhere on the great big Internet, but it&amp;#39;s new to me.&amp;#160; And it sucked until I discovered what the problem was.&amp;#160; Basically, I had random values being generated that were anything but random.&amp;#160; &amp;quot;Oh, you forgot to set a seed value to something pseudo-random like now.millisecond.&amp;quot;&amp;#160; No.&amp;#160; That didn&amp;#39;t help.&amp;#160; Check out this code and see what the results are: &lt;/p&gt;  &lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt; UnRandom()
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; r &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; Random(Now.Millisecond)

        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; winCount, winCount2 &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;

        &lt;span class="kwrd"&gt;For&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 1 &lt;span class="kwrd"&gt;To&lt;/span&gt; 100
            &lt;span class="kwrd"&gt;If&lt;/span&gt; Rndm() &amp;gt; 50 &lt;span class="kwrd"&gt;Then&lt;/span&gt; winCount += 1
        &lt;span class="kwrd"&gt;Next&lt;/span&gt;

        &lt;span class="kwrd"&gt;For&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 1 &lt;span class="kwrd"&gt;To&lt;/span&gt; 100
            &lt;span class="kwrd"&gt;If&lt;/span&gt; r.&lt;span class="kwrd"&gt;Next&lt;/span&gt;(1, 100) &amp;gt; 50 &lt;span class="kwrd"&gt;Then&lt;/span&gt; winCount2 += 1
        &lt;span class="kwrd"&gt;Next&lt;/span&gt;

        MsgBox(winCount &amp;amp; &lt;span class="str"&gt;&amp;quot;:&amp;quot;&lt;/span&gt; &amp;amp; winCount2)

    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Sub&lt;/span&gt;

    &lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; Rndm() &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt;
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; r &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;New&lt;/span&gt; Random(Now.Millisecond)

        &lt;span class="kwrd"&gt;Return&lt;/span&gt; r.&lt;span class="kwrd"&gt;Next&lt;/span&gt;(1, 100)
    &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Assuming a 50/50 chance of win, you would expect that a Random.Next would return a random value.&amp;#160; Seemingly not when it gets continually instantiated like in the Rndm function.&amp;#160; So this apparently is not a case where you want all of your variables to be contained in their own methods.&amp;#160; You&amp;#39;d probably want to have one single random number generator for your whole application.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=247" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry><entry><title>Using GDI+ To Create Depth Perspective</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/06/19/using-gdi-to-create-depth-perspective.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/06/19/using-gdi-to-create-depth-perspective.aspx</id><published>2008-06-20T00:53:33Z</published><updated>2008-06-20T00:53:33Z</updated><content type="html">&lt;p&gt;This is a quick little bit of code that I made up after unsuccessfully finding anyone else that had done it.&amp;#160; What I wanted to do is take an original image, and skew it so it looked like it was going off into the distance.&amp;#160; That gives it perspective.&amp;#160; Obviously something like that is going to be used in this game I&amp;#39;m working and blogging on.&amp;#160; More precisely, it&amp;#39;ll be part of the map-building tools.&lt;/p&gt;  &lt;p&gt;So you start with an image like: &lt;img src="http://www.700cb.net/images/blog/frontwall.png" alt="" /&gt;&amp;#160; and you end up with an image like: &lt;img src="http://www.700cb.net/images/blog/frontwallskewed.png" alt="" /&gt; .&amp;#160; That&amp;#39;s a 50% skew.&amp;#160; The image should be half as tall at the end and is half as wide as the original.&amp;#160; I didn&amp;#39;t see any built-in way in GDI+ to transform the image, so I did it by brute force.&amp;#160; Here&amp;#39;s a reusable function to do the magic:&lt;/p&gt;  &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;Private&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt; PerspectiveImage(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; sourceImage &lt;span class="kwrd"&gt;As&lt;/span&gt; Image, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; perspective &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Single&lt;/span&gt;) &lt;span class="kwrd"&gt;As&lt;/span&gt; Image
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; destImage &lt;span class="kwrd"&gt;As&lt;/span&gt; Image
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; destGr &lt;span class="kwrd"&gt;As&lt;/span&gt; Graphics
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; sourceSection &lt;span class="kwrd"&gt;As&lt;/span&gt; RectangleF
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; destSection &lt;span class="kwrd"&gt;As&lt;/span&gt; RectangleF
    &lt;span class="kwrd"&gt;Dim&lt;/span&gt; factor &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Double&lt;/span&gt;

    destImage = &lt;span class="kwrd"&gt;New&lt;/span&gt; Bitmap(&lt;span class="kwrd"&gt;CInt&lt;/span&gt;(sourceImage.Width * perspective), _ 
        sourceImage.Height, Imaging.PixelFormat.Format32bppArgb)

    destGr = Graphics.FromImage(destImage)

    &lt;span class="kwrd"&gt;For&lt;/span&gt; i &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;Integer&lt;/span&gt; = 0 &lt;span class="kwrd"&gt;To&lt;/span&gt; sourceImage.Width
        &lt;span class="kwrd"&gt;With&lt;/span&gt; sourceSection
            .Height = sourceImage.Height
            .Width = 1
            .X = i
            .Y = 0
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;With&lt;/span&gt;

        factor = perspective * (i / sourceImage.Width)

        &lt;span class="kwrd"&gt;With&lt;/span&gt; destSection
            .Height = &lt;span class="kwrd"&gt;CSng&lt;/span&gt;(sourceSection.Height - (sourceSection.Height * factor))
            .Width = 1
            .X = &lt;span class="kwrd"&gt;CSng&lt;/span&gt;(i * perspective)
            .Y = &lt;span class="kwrd"&gt;CSng&lt;/span&gt;((sourceSection.Height - .Height) / 2)
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;With&lt;/span&gt;

        destGr.DrawImage(sourceImage, destSection, sourceSection, GraphicsUnit.Pixel)
    &lt;span class="kwrd"&gt;Next&lt;/span&gt;

    destGr.Dispose()

    &lt;span class="kwrd"&gt;Return&lt;/span&gt; destImage

&lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Function&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Basically it runs through the source image copying column by column of the image, then pasting it into the destination image at a calculated scale.&amp;#160; You can add the value checking yourself to make sure the perspective parameter is a positive number and should be between .1 and .9.&amp;#160; Well, you can do values greater than 1, but it&amp;#39;s kinda weird looking.&amp;#160; Enjoy.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=246" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry><entry><title>XNA Zune Games in VB</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/06/12/xna-zune-games-in-vb.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/06/12/xna-zune-games-in-vb.aspx</id><published>2008-06-12T02:26:00Z</published><updated>2008-06-12T02:26:00Z</updated><content type="html">&lt;p&gt;I&amp;#39;ve been spending a lot of time working on the game-play for the dungeon-type game for the Zune. Along the way, I&amp;#39;ve learned a lot about XNA. It&amp;#39;s not as bad as I thought. It&amp;#39;s just a bunch of new classes to understand. The programming concepts are still the same. I was initially worried that XNA would be so limited as to require a more procedural approach to coding, but I&amp;#39;m glad to see that&amp;#39;s not true. I have classes, inheritance, and events. That&amp;#39;s all I need to start.&lt;/p&gt;  &lt;p&gt;I&amp;#39;d been doing pretty well testing the game out in a winform container, but I really wanted to see how it would run on the Zune. Unfortunately, every time I started the game on the Zune, it would reboot. I knew that the Zune XNA didn&amp;#39;t support VB, so I researched getting rid of the reference to the VB runtime. I found the magic switch and recompiled. The VB runtime was gone. I thought that was it, but I still had more to go. Every few days, I&amp;#39;d try again and see if it would dawn on me. Tonight it did. I still had a reference to the 2.0 mscorlib in addition to the 3.5 version. After setting another magic switch, I was able to run the game on the Zune. Happiness!&lt;/p&gt;  &lt;p&gt;So, here&amp;#39;s what I did. I created a batch file, build.bat. I built the project in VS2005 and copied the vbc.exe command line out of the output window. I pasted this into the batch file. Then I made the following changes.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Original:&lt;/strong&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Vbc.exe /noconfig /imports:System,System.Collections,System.Collections.Generic /nowarn:42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 /optionstrict+ /rootnamespace:DungeonXNAGame /doc:obj\Release\DungeonXNAGame.xml /define:&amp;quot;CONFIG=\&amp;quot;Release\&amp;quot;,TRACE=-1,_MyType=\&amp;quot;WindowsFormsWithCustomSubMain\&amp;quot;,PLATFORM=\&amp;quot;AnyCPU\&amp;quot;&amp;quot; /reference:D:\Projects\cbDungeon\DungeonObjects\bin\Release\DungeonObjects.dll,&amp;quot;C:\Program Files\Microsoft XNA\XNA Game Studio\v3.0\References\Windows\x86\Microsoft.Xna.Framework.dll&amp;quot;,&amp;quot;C:\Program Files\Microsoft XNA\XNA Game Studio\v3.0\References\Windows\x86\Microsoft.Xna.Framework.Game.dll&amp;quot;,C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Deployment.dll, 
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll,C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Windows.Forms.dll, 
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.XML.dll /debug- /optimize+ /out:obj\Release\DungeonXNAGame.exe 
/target:winexe Components\CompassComponent.vb Components\MapComponent.vb DungeonXNAGame.vb GameStart.vb &amp;quot;My Project\AssemblyInfo.vb&amp;quot;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;Changed:&lt;/strong&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;C:\WINDOWS\Microsoft.NET\Framework\v3.5\Vbc.exe /sdkpath:&amp;quot;C:\Program Files\Microsoft XNA\XNA Game Studio\v3.0\References\Zune&amp;quot; /noconfig /verbose /nostdlib /novbruntimeref /imports:System,System.Collections,System.Collections.Generic /nowarn:42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 /optionstrict+ /rootnamespace:DungeonXNAGame /define:&amp;quot;_MyType=\&amp;quot;Empty\&amp;quot;&amp;quot; /reference:D:\Projects\cbDungeon\DungeonObjects\bin\Release\DungeonObjects.dll,&amp;quot;C:\Program Files\Microsoft XNA\XNA Game Studio\v3.0\References\Zune\Microsoft.Xna.Framework.dll&amp;quot;,&amp;quot;C:\Program Files\Microsoft XNA\XNA Game Studio\v3.0\References\Zune\Microsoft.Xna.Framework.Game.dll&amp;quot;,&amp;quot;c:\Program Files\Microsoft XNA\XNA Game Studio\v3.0\References\Zune\System.Xml.dll&amp;quot; /debug- /optimize+ /out:bin\Release\DungeonXNAGame.dll /target:library Components\CompassComponent.vb Components\MapComponent.vb DungeonXNAGame.vb &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Can you spot the differences? Here they are:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Path to vbc.exe changed from version v2.0.50727 to v3.0 &lt;/li&gt;    &lt;li&gt;Added /sdkpath switch. This points to the XNA framework root for the Zune files. This gets rid of the mscorlib 2.0 reference &lt;/li&gt;    &lt;li&gt;Added /verbose (so I can see what&amp;#39;s going on) &lt;/li&gt;    &lt;li&gt;Added /nostdlib (gets rid of unneeded references) &lt;/li&gt;    &lt;li&gt;Added /novbruntimeref (gets rid of Microsoft.VisualBasic reference) &lt;/li&gt;    &lt;li&gt;Modified references to point to Zune versions of DLLs &lt;/li&gt;    &lt;li&gt;Changed /define switch to use \&amp;quot;Empty\&amp;quot; This makes sure that the &amp;quot;My&amp;quot; namespace is not created. Creating the My namespace results in a reference to the VB runtime. &lt;/li&gt;    &lt;li&gt;Changed output type and destination with /out and /target &lt;/li&gt;    &lt;li&gt;Removed reference to assemblyinfo.vb. That might not be required, but just to be minimal... &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;So the main switches you need to work with are: /sdkpath, /novbruntimeref and /define and also make sure you use the right vbc version (3.0). Just use that build.bat from the command line to create your libraries.&lt;/p&gt;  &lt;p&gt;Now that I&amp;#39;ve seen the game run on the Zune, I&amp;#39;m going to drop my reservations about coding the game in VB. All the C# snobs who think they&amp;#39;re the only ones that matter can go suck a semicolon.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=245" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry><entry><title>Now a little less than fun project</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/06/01/now-a-little-less-than-fun-project.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/06/01/now-a-little-less-than-fun-project.aspx</id><published>2008-06-02T00:08:08Z</published><updated>2008-06-02T00:08:08Z</updated><content type="html">&lt;p&gt;A few very productive days with lots of progress... lots of momentum.&amp;#160; That&amp;#39;s always trouble when you come up to &amp;quot;the wall.&amp;quot;&amp;#160; The momentum you have gained certainly works against you.&lt;/p&gt;  &lt;p&gt;So in the few days, I created a usable map editor for the game: &lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.700cb.net/images/zune/mapmaintenance.jpg" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;I created a test application to walk through the created maps:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.700cb.net/images/zune/maptest.jpg" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;And then I created the graphical version using XNA:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://www.700cb.net/images/zune/mapzuneformat.jpg" alt="" /&gt; &lt;/p&gt;  &lt;p&gt;So I&amp;#39;m thinking I&amp;#39;m good to go.&amp;#160; Even though I&amp;#39;ve written everything in VB, I should still be able to make it work.&amp;#160; It&amp;#39;s all .NET, right?&lt;/p&gt;  &lt;p&gt;First, I make the C# XNA game project and reference my VB.NET DLL.&amp;#160; Point the code to the proper methods in the DLL as needed and now compile.&amp;#160; But it doesn&amp;#39;t compile.&amp;#160; Some error about needing a reference to Xna.Framework and Xna.Framework.Game.&amp;#160; Well, of course I have those.&amp;#160; After deeper investigation, there are two different Xna.Framework (and.Game) DLLs.&amp;#160; One for Windows and one for the Zune.&amp;#160; Guess which one I was referencing?&amp;#160; The other one.&amp;#160; That&amp;#39;s why it worked so well in the Windows build of the game.&lt;/p&gt;  &lt;p&gt;More juggling of code, DLLs and references and eventually rewriting all my XNA code in C# (Gah.), I got a good compile and deployment to the Zune.&amp;#160; However, now it just doesn&amp;#39;t start.&amp;#160; The Zune reboots before starting the game.&amp;#160; How do you troubleshoot something like that?&lt;/p&gt;  &lt;p&gt;I&amp;#39;ve hit the wall and it&amp;#39;s time to walk away.&amp;#160; Just walk away.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=243" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry><entry><title>A new fun project</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/05/30/a-new-fun-project.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/05/30/a-new-fun-project.aspx</id><published>2008-05-30T02:16:45Z</published><updated>2008-05-30T02:16:45Z</updated><content type="html">&lt;p&gt;As most everyone should know, the Zune is doing games now.&amp;#160; XNA games, that is.&amp;#160; Well, I&amp;#39;m no XNA person, but I suspect I should be able to write a DLL in .NET for someone who does write XNA to implement.&lt;/p&gt;  &lt;p&gt;So I kicked around that idea for a while and wondered, what should I write?&amp;#160; Today it just kind of came to me: a Wizardry clone - a generic adventure game.&amp;#160; I&amp;#39;d written text based adventures many years ago in BASIC, so the concepts and program structure were pretty familiar to me.&amp;#160; So I sat down with a piece of paper and sketched out some objects.&lt;/p&gt;  &lt;p&gt;I didn&amp;#39;t want to get overwhelmed in the design phase and end up discovering I couldn&amp;#39;t do what I wanted and wind up discouraged, so I started with the map concept.&amp;#160; I decided every location would be an object.&amp;#160; It needed to know what direction the exits were and the position of the location on the map.&amp;#160; To keep size to a minimum, I compressed these to two integers (or shorts if I get really desperate).&amp;#160; I added an extra integer for special flags, like dark or pit or poison.&lt;/p&gt;  &lt;p&gt;Then I map a map object which is just a collection of map locations.&amp;#160; Actually a dictionary, so I can look up map locations quickly using the position value.&lt;/p&gt;  &lt;p&gt;So I sketched out on grid paper a couple of corridors.&amp;#160; I manually calculated the exit and position values and put them in the code.&amp;#160; Then I wrote a quick test app to move from location to location using buttons.&amp;#160; It worked on the first try!&lt;/p&gt;  &lt;p&gt;Feeling good about that, I made a quick form where I could draw a map on a panel and generate the map values, then immediately &amp;quot;walk through&amp;quot; the map.&amp;#160; That worked without a hitch too!&lt;/p&gt;  &lt;p&gt;So I&amp;#39;m pretty thrilled that I&amp;#39;ve been able to get this far in only a couple of hours.&amp;#160; Anymore it seems like I spend forever on design, or start something only to find that it&amp;#39;s just way too big to tackle, or just lose interest midway through.&lt;/p&gt;  &lt;p&gt;Yay, me.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=242" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry><entry><title>Testing Windows Live Writer</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/05/10/testing-windows-live-writer.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/05/10/testing-windows-live-writer.aspx</id><published>2008-05-10T16:39:42Z</published><updated>2008-05-10T16:39:42Z</updated><content type="html">&lt;p&gt;This is going to be a test of how Windows Live Writer works with my blog on SOAPitStop.&amp;#160; So far, most of seems pretty good.&amp;#160; The web layout function doesn&amp;#39;t really honor line wrapping, so I&amp;#39;ll just compose in normal view.&lt;/p&gt;  &lt;p&gt;I also downloaded a plugin to format code.&amp;#160; Let&amp;#39;s test that out.&amp;#160; Here&amp;#39;s a bit of code that posts an NNTP message to an Exchange newsgroup server (config is a custom class I wrote.&amp;#160; It should be easy to figure out what it does and what&amp;#39;s in it):&lt;/p&gt;  &lt;pre class="csharpcode"&gt;    &lt;span class="kwrd"&gt;Sub&lt;/span&gt; SendNNTP(&lt;span class="kwrd"&gt;ByVal&lt;/span&gt; newsgroup &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; from &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; subject &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;, &lt;span class="kwrd"&gt;ByVal&lt;/span&gt; body &lt;span class="kwrd"&gt;As&lt;/span&gt; &lt;span class="kwrd"&gt;String&lt;/span&gt;)
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; c &lt;span class="kwrd"&gt;As&lt;/span&gt; CDO.Configuration
        &lt;span class="kwrd"&gt;Dim&lt;/span&gt; m &lt;span class="kwrd"&gt;As&lt;/span&gt; CDO.Message

        c = &lt;span class="kwrd"&gt;New&lt;/span&gt; CDO.Configuration
        &lt;span class="kwrd"&gt;With&lt;/span&gt; c

            .Fields(CDO.CdoConfiguration.cdoPostUsingMethod).Value = CDO.CdoPostUsing.cdoPostUsingPort
            .Fields(CDO.CdoConfiguration.cdoNNTPServer).Value = config.destinationServer.NewsgroupServer
            &lt;span class="kwrd"&gt;Select&lt;/span&gt; &lt;span class="kwrd"&gt;Case&lt;/span&gt; config.destinationServer.AuthMethod
                &lt;span class="kwrd"&gt;Case&lt;/span&gt; ServerConfig.AuthMethods.Basic
                    .Fields(CDO.CdoConfiguration.cdoNNTPAuthenticate).Value = CDO.CdoProtocolsAuthentication.cdoBasic
                    .Fields(CDO.CdoConfiguration.cdoPostUserName).Value = config.destinationServer.UserName
                    .Fields(CDO.CdoConfiguration.cdoPostPassword).Value = config.destinationServer.Password

                &lt;span class="kwrd"&gt;Case&lt;/span&gt; ServerConfig.AuthMethods.NTLM
                    .Fields(CDO.CdoConfiguration.cdoNNTPAuthenticate).Value = CDO.CdoProtocolsAuthentication.cdoNTLM

                &lt;span class="kwrd"&gt;Case&lt;/span&gt; ServerConfig.AuthMethods.None
                    &lt;span class="rem"&gt;&amp;#39; Nothing&lt;/span&gt;

            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Select&lt;/span&gt;
            .Fields.Update()
        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;With&lt;/span&gt;

        &lt;span class="kwrd"&gt;Try&lt;/span&gt;
            m = &lt;span class="kwrd"&gt;New&lt;/span&gt; CDO.Message
            &lt;span class="kwrd"&gt;With&lt;/span&gt; m
                .Configuration = c
                .Newsgroups = newsgroup
                .From = from
                .Subject = subject
                .TextBody = body
                .Post()
            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;With&lt;/span&gt;

        &lt;span class="kwrd"&gt;Catch&lt;/span&gt; ex &lt;span class="kwrd"&gt;As&lt;/span&gt; System.runtime.InteropServices.COMException
            &lt;span class="kwrd"&gt;If&lt;/span&gt; ex.Message.IndexOf(&lt;span class="str"&gt;&amp;quot;Article Rejected -- No such groups&amp;quot;&lt;/span&gt;) &amp;gt; -1 &lt;span class="kwrd"&gt;Then&lt;/span&gt;
                Console.WriteLine(&lt;span class="str"&gt;&amp;quot;Error sending mesage: No such group on destination server&amp;quot;&lt;/span&gt;)
                &lt;span class="kwrd"&gt;Exit&lt;/span&gt; &lt;span class="kwrd"&gt;Try&lt;/span&gt;
            &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;If&lt;/span&gt;

            Console.WriteLine(&lt;span class="str"&gt;&amp;quot;Error sending message: &amp;quot;&lt;/span&gt; &amp;amp; ex.Message)

        &lt;span class="kwrd"&gt;End&lt;/span&gt; &lt;span class="kwrd"&gt;Try&lt;/span&gt;

    &lt;span class="kwrd"&gt;End&lt;/span&gt; Sub&lt;/pre&gt;

&lt;p&gt;That&amp;#39;s not too bad, I guess.&amp;#160; Now maybe I can blog a little bit easier since I don&amp;#39;t have to log in, write my post, manually reformat it to HTML, then post it.&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=241" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry><entry><title>Reading This Worthless Post... (2 minutes, 1 second remaining)</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/04/25/reading-this-worthless-post-2-minutes-1-second-remaining.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/04/25/reading-this-worthless-post-2-minutes-1-second-remaining.aspx</id><published>2008-04-25T01:47:00Z</published><updated>2008-04-25T01:47:00Z</updated><content type="html">&lt;p&gt;
A really great book with some timeless information is Developing User Interfaces for Microsoft Windows.  One of the things that I got out of it, implicitly or explicitly, is the need for user feedback.  And I started making it a higher priority in my applications.
&lt;/p&gt;
&lt;p&gt;
One of the things I did was create a reusable progress dialog.  And I wanted it to be as informational as possible, which meant it had to have remaining time reported.  Here&amp;#39;s how I did it:
&lt;/p&gt;
&lt;p&gt;

I started with a form with a progress bar and a label (ProgressBar1 and lblTimeRemaining, yeah, I&amp;#39;m consistent).  In the code, I created a private variable for start time.  I reset the start time on the Shown event of the form.
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
Private startTime As Date

Private Sub frmProgress_Shown(ByVal sender As Object, _ 
	ByVal e As System.EventArgs) Handles Me.Shown
	
	startTime = Now
	
End Sub
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
Then I created a public sub that would accept the current item and the total items.  The sub would update the progress bar and calculate the time left.  A helper function would convert the time into a well-formatted string.  That&amp;#39;s really my favorite part of the whole thing, but this whole post is pretty &amp;quot;so what&amp;quot; anyway, so there.
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
Public Sub UpdateTime(ByVal currentItem As Integer, _ 
	ByVal totalItems As Integer)
	
	Dim elapsed As TimeSpan
	Dim remaining As TimeSpan
	Dim secsPerItem As Double
	Dim tempSeconds As Double
	Dim remainingMessage As String = &amp;quot;&amp;quot;

	&amp;#39; Handle 0-based counts
	If currentItem = 0 Then
		currentItem += 1
		totalItems += 1
	End If

	With ProgressBar1
		.Maximum = totalItems
		.Value = currentItem
	End With

	&amp;#39; get the amount of time that has passed since the process was started
	elapsed = Now.Subtract(startTime)

	&amp;#39; get average number of seconds per item
	secsPerItem = elapsed.TotalSeconds / currentItem

	&amp;#39; Figure out how many seocnds are left based on the number of items left
	&amp;#39; Don&amp;#39;t let the seconds exceed the max for an integer
	tempSeconds = secsPerItem * (totalItems - currentItem)
	If tempSeconds &amp;gt; Integer.MaxValue Then tempSeconds = Integer.MaxValue

	remaining = New TimeSpan(0, 0, CInt(tempSeconds))

	remainingMessage = TimeString(remaining)

	If remainingMessage &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then
		lblTimeRemaining.Text = remainingMessage &amp;amp; &amp;quot; remaining&amp;quot;
	Else
		lblTimeRemaining.Text = &amp;quot;&amp;quot;
	End If

End Sub

Private Function TimeString(ByVal span As TimeSpan) As String
	Dim msg As New System.Text.StringBuilder
	&amp;#39; Make a proper time remaining message
	With msg
		If span.Hours &amp;gt; 0 Then
			.Append(span.Hours &amp;amp; &amp;quot; hour&amp;quot;)
			.Append(IIf(span.Hours &amp;gt; 1, &amp;quot;s&amp;quot;, &amp;quot;&amp;quot;))
			.Append(&amp;quot;, &amp;quot;)
		End If

		If span.Hours &amp;gt; 0 OrElse span.Minutes &amp;gt; 0 Then
			.Append(span.Minutes &amp;amp; &amp;quot; minute&amp;quot;)
			.Append(IIf(span.Minutes &amp;gt; 1, &amp;quot;s&amp;quot;, &amp;quot;&amp;quot;))
			.Append(&amp;quot;, &amp;quot;)
		End If

		If span.Hours = 0 AndAlso span.Seconds &amp;lt;&amp;gt; 0 Then
			.Append(span.Seconds &amp;amp; &amp;quot; second&amp;quot;)
			.Append(IIf(span.Seconds &amp;gt; 1, &amp;quot;s&amp;quot;, &amp;quot;&amp;quot;))
			.Append(&amp;quot;, &amp;quot;)
		End If

		If .Length &amp;gt; 0 Then .Length -= 2

	End With

	Return msg.ToString

End Function
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
Why do I like the TimeString function so much?  It must be because of the extra care it takes.  Obvious things like adding an &amp;quot;s&amp;quot; when there&amp;#39;s multiple hours, somewhat obvious things like not displaying &amp;quot;0 minutes&amp;quot;, and not so obvious things like not bothering to show seconds when there&amp;#39;s an hour or more remaining.  It just makes me feel like I paid attention, which anymore is such a fleeting feeling.
&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=240" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry><entry><title>In Log We Trust (or why did you have to make it so difficult?)</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/04/17/in-log-we-trust-or-why-did-you-have-to-make-it-so-difficult.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/04/17/in-log-we-trust-or-why-did-you-have-to-make-it-so-difficult.aspx</id><published>2008-04-17T01:04:00Z</published><updated>2008-04-17T01:04:00Z</updated><content type="html">&lt;p&gt;I guess this might be kind of a belated rant... some will know what i&amp;#39;m talking about.
At a previous job, we had a need to log stuff: errors, debug info, etc.  We were given an API by the upper programmers and it was, shall we say, less than excellent.  It was based on some MS application block, which had dependancies on a bunch of other application blocks and made your config files massive.  But, boy was it configurable.  Blah.  The most difficult part was writing out the signature of the method and the parameters.  We couldn&amp;#39;t consider doing the values passed in yet.  Every time we changed the method signature, we had to alter all the logging statements.  We usually ignored logging until late in development when the methods would stabilize.
&lt;/p&gt;&lt;p&gt;
So I proposed a more simple way.  I mean, Reflection is supposed to know all this stuff, right?  Why not have it interrogate the current method and pass it and its parameters somewhere to be logged, or at least generated.  It was declined.  I didn&amp;#39;t take it personally, but inside I was using an evil villain voice: &amp;quot;you fools!&amp;quot;
&lt;/p&gt;&lt;p&gt;
So when I left, I took my ideas with me and quickly built this into my new application suite.  It&amp;#39;s not as wicked-cool as having a config file that can switch between text file and sql logging, in fact, it has NO config file.  The simplicity of the logging is the key.
&lt;/p&gt;&lt;p&gt;
So let&amp;#39;s say you want to log an error.  This is all you write:
&lt;/p&gt;&lt;p&gt;&lt;pre&gt;
Try

Catch ex As Exception
	Logging.LogError(ex, System.Reflection.MethodInfo.GetCurrentMethod)

End Try
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;
And it&amp;#39;s the same for every method.  That right there is worth its weight in code.  But what about when you have parameters?  You would need to capture them too.  The code is almost unbearable at that point, right?
&lt;/p&gt;&lt;p&gt;&lt;pre&gt;
Try

Catch ex As Exception
	Dim errorParms As New System.Collections.Specialized.StringCollection
	With errorParms
		.Add(parm1)
		.Add(parm2.ToString)
	End With
	Logging.LogError(ex, System.Reflection.MethodInfo.GetCurrentMethod, errorParms)
End Try
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;
So what&amp;#39;s the error log look like?  It&amp;#39;s tab-delimited and has the basics of what you need:
&lt;/p&gt;&lt;p&gt;

DATE	USER	METHOD	ERROR MESSAGE&lt;br /&gt;
4/16/2008 9:04:30 PM	700CB\anachostic	WindowsApplication1.Form1.LogWithoutParameters(parm1,parm2)	This is a generated error.&lt;br /&gt;
4/16/2008 9:04:30 PM	700CB\anachostic	WindowsApplication1.Form1.LogWithParameters(parm1=This is parm 1,parm2=12345)	This is a generated error.&lt;br /&gt;


&lt;/p&gt;&lt;p&gt;
Have I sold it yet?  Or at least given you a starting point for your own logging &amp;quot;framework&amp;quot;?  Ahem.  Please, it&amp;#39;s just a simple class.  Here it is for your plunder:
&lt;/p&gt;&lt;p&gt;&lt;pre&gt;
Imports System.Reflection
Imports System.Collections.Specialized

Public Class Logging

    Public Shared LOGFILE_NAME As String

    Shared Sub New()
        LOGFILE_NAME = &amp;quot;c:\&amp;quot; &amp;amp; My.Application.Info.ProductName &amp;amp; &amp;quot;-Errors.log&amp;quot;

    End Sub

    Shared Sub LogError(ByVal ex As Exception, ByVal method As MethodBase)
        LogError(ex, method, Nothing)
    End Sub

    Shared Sub LogError(ByVal ex As Exception, ByVal method As MethodBase, _
        ByVal parameterValues As StringCollection)

        Dim sb As New System.Text.StringBuilder

        Try
            With sb
                .Append(Now.ToString)
                .Append(vbTab)
                .Append(My.User.CurrentPrincipal.Identity.Name)
                .Append(vbTab)

                If method IsNot Nothing Then
                    .Append(method.ReflectedType.FullName &amp;amp; &amp;quot;.&amp;quot; &amp;amp; method.Name)
                    .Append(&amp;quot;(&amp;quot;)


                    For i As Integer = 0 To method.GetParameters.Length - 1
                        .Append(method.GetParameters(i).Name)
                        If parameterValues IsNot Nothing _
                            AndAlso i &amp;lt; parameterValues.Count Then
                            .Append(&amp;quot;=&amp;quot; &amp;amp; parameterValues(i).Replace(vbCrLf, &amp;quot;&amp;lt;CR&amp;gt;&amp;quot;))
                        End If

                        .Append(&amp;quot;,&amp;quot;)

                    Next

                    If sb.ToString.EndsWith(&amp;quot;,&amp;quot;) Then sb.Length -= 1

                    .Append(&amp;quot;)&amp;quot;)

                End If

                .Append(vbTab)

                If ex IsNot Nothing Then
                    .Append(ex.Message.Replace(vbCrLf, &amp;quot;&amp;lt;CR&amp;gt;&amp;quot;))
                End If

            End With

        Catch exc As Exception
            sb.Append(&amp;quot;&amp;lt;ERROR WHILE PARSING: &amp;quot; &amp;amp; exc.Message &amp;amp; &amp;quot;&amp;gt;&amp;quot;)
        End Try

        LogMessage(sb.ToString)

    End Sub

    Shared Sub LogMessage(ByVal msg As String)
        Try
            If Not IO.File.Exists(LOGFILE_NAME) Then
                IO.File.WriteAllText(LOGFILE_NAME, &amp;quot;DATE&amp;quot; _
                    &amp;amp; vbTab &amp;amp; &amp;quot;USER&amp;quot; _
                    &amp;amp; vbTab &amp;amp; &amp;quot;METHOD&amp;quot; _
                    &amp;amp; vbTab &amp;amp; &amp;quot;ERROR MESSAGE&amp;quot; _
                    &amp;amp; vbCrLf)

            End If

            IO.File.AppendAllText(LOGFILE_NAME, msg &amp;amp; vbCrLf)

        Catch ex As Exception

        End Try

    End Sub

End Class
&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;P.S., I&amp;#39;m still using the same blog, guys...&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=238" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry><entry><title>In CASE you were wondering...</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/04/11/in-case-you-were-wondering.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/04/11/in-case-you-were-wondering.aspx</id><published>2008-04-11T22:12:00Z</published><updated>2008-04-11T22:12:00Z</updated><content type="html">&lt;p&gt;
Here&amp;#39;s a thought I had a couple of days ago.  I actually was almost done with this blog entry yesterday, but ended up closing the window and not saving any of it.  Argh.
&lt;/p&gt;&lt;p&gt;
My thought was on sql sorting.  There are times when you want to have your results sorted at the server based on a parameter.  Those of you who like dynamic sql would be all over that.  It&amp;#39;s so simple (in Northwind):
&lt;/p&gt;&lt;p&gt;&lt;pre&gt;
declare @SortType int
declare @sql varchar(2000)
-- SortTypes
-- 1- Lastname
-- 2- Firstname
-- 3- Employeeed
-- 4- Extension
-- 5- postalcode

set @sorttype=4

set @sql=&amp;#39;select * from employees&amp;#39;
if @sorttype=1 set @sql=@sql + &amp;#39; order by lastname&amp;#39;
if @sorttype=2 set @sql=@sql + &amp;#39; order by firstname&amp;#39;
if @sorttype=3 set @sql=@sql + &amp;#39; order by employeeid&amp;#39;
if @sorttype=4 set @sql=@sql + &amp;#39; order by extension&amp;#39;
if @sorttype=5 set @sql=@sql + &amp;#39; order by postalcode&amp;#39;

exec(@sql)
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;
Ok.  But as I&amp;#39;ve said before, I am not a fan of dynamic sql.  And my environment doesn&amp;#39;t allow it because all security is done through the stored procedures.  So, how do we do the same thing without dynamic sql?  It&amp;#39;s a great use of the CASE function.
&lt;/p&gt;&lt;p&gt;
Let&amp;#39;s start with the first two sort types: lastname and firstname.  you can put the CASE in the ORDER BY section:
&lt;/p&gt;&lt;p&gt;&lt;pre&gt;
select *
from employees
order by case @sorttype
	when 1 then lastname
	when 2 then firstname
	end 
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;
That was simple.  So let&amp;#39;s add the third type, employeeid.
&lt;/p&gt;&lt;p&gt;&lt;pre&gt;
order by case @sorttype
	when 1 then lastname
	when 2 then firstname
	when 3 then employeeid
	end
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;	
Works well.  Wait, no it doesn&amp;#39;t.  Sorting by type 3 is fine, but sorting bu type 1 or 2 gives:
&lt;/p&gt;&lt;p&gt;&lt;pre&gt;
Msg 245, Level 16, State 1, Line 12
Conversion failed when converting the nvarchar value &amp;#39;Davolio&amp;#39; to data type int.
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;
Ok, that&amp;#39;s not a problem, we&amp;#39;ll just convert everything to varchar.  So now it&amp;#39;s like:
&lt;/p&gt;&lt;p&gt;&lt;pre&gt;
order by case @sorttype
	when 1 then lastname
	when 2 then firstname
	when 3 then cast(employeeid as varchar)
	end 
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;
That works, kind of.  You won&amp;#39;t notice the bug on Northwind, but you will when we do the next type, extension.  We need to convert it to varchar also.
&lt;/p&gt;&lt;p&gt;&lt;pre&gt;
order by case @sorttype
	when 1 then lastname
	when 2 then firstname
	when 3 then cast(employeeid as varchar)
	when 4 then cast(extension as varchar)
	end 
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;
Wow, that&amp;#39;s not right.  2344 doesn&amp;#39;t come before 428.  But it does in the string world, which you forced your way into.  There is a solution.  we just need to pad the numbers with zeros.  But how many zeros?  All the values have to be the same length to be considered equivalent.  so now we have:
&lt;/p&gt;&lt;p&gt;&lt;pre&gt;
order by case @sorttype
	when 1 then lastname
	when 2 then firstname
	when 3 then cast(employeeid as varchar)
	when 4 then replicate(&amp;#39;0&amp;#39;,10-len(extension))+ extension
	end 
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;
That works fine.  And we&amp;#39;ll have the same problem with postalcode, which is numeric and character, so we need to pad the beginning of those to be equal-length strings.  The final version:
&lt;/p&gt;&lt;p&gt;&lt;pre&gt;
select *
from employees
order by case @sorttype
	when 1 then lastname
	when 2 then firstname
	when 3 then cast(employeeid as varchar)
	when 4 then replicate(&amp;#39;0&amp;#39;,10-len(extension))+ extension
	when 5 then replicate(&amp;#39;0&amp;#39;,20-len(postalcode))+ postalcode
	end 
&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;	
You&amp;#39;d want to make the length of the postalcode be the max length of the field, in case it&amp;#39;s blank.  But the point is CASE is a very powerful tool.  It can be used anywhere a single value can be used.  In ORDER BY, in JOIN, in SELECT, it&amp;#39;s universal.  Now I&amp;#39;m going to save this before I lose it again.
&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=235" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry><entry><title>The Zune Application is Guilty of Flash over Function.  Kick It.</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/03/10/the-zune-application-is-guilty-of-flash-over-function-kick-it.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/03/10/the-zune-application-is-guilty-of-flash-over-function-kick-it.aspx</id><published>2008-03-11T00:08:00Z</published><updated>2008-03-11T00:08:00Z</updated><content type="html">&lt;p&gt;
Don&amp;#39;t get me wrong, I love the Zune, but the new interface is beautiful to a fault.  Like Beauty and the Geek, it&amp;#39;s nice to look at, but you can&amp;#39;t really hold a conversation with it.  It&amp;#39;s like it&amp;#39;s always in the bathroom fixing its hair or makeup.  I was doing more poking around the Zune files and I found some command-line options to try.  The most interesting one disables the DirectX effects and should make the UI a lot snappier for those that just don&amp;#39;t have the horsepower or the desire for a really flashy interface.  I think I know who you are.
&lt;/p&gt;&lt;p&gt;
The command-line options I found:
&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;b&gt;-animations:(true|false)&lt;/b&gt;  Enable or disable fading effects.&lt;/li&gt;
	&lt;li&gt;&lt;b&gt;-gdi&lt;/b&gt; Use GDI instead of DirectX, seems to disable animations and probably give some legacy support.  This is mentioned in the Zune 2.3 release notes.&lt;/li&gt;
	&lt;li&gt;&lt;b&gt;-switchtogdi&lt;/b&gt; Permanently switch to GDI rendering.  makes registry entry change in general settings: HKEY_CURRENT_USER\Software\Microsoft\Zune\GeneralSettings\UseGDI=1&lt;/li&gt;
	&lt;li&gt;&lt;b&gt;-dx9&lt;/b&gt; Use DirectX9 compatibility?  Probably.&lt;/li&gt;
	&lt;li&gt;&lt;b&gt;-direction:(rtl|ltr)&lt;/b&gt; Use Right-to-Left rendering for languages that require it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
So for example, you want to start by disabling the fancy slide and fade animations to see what effect that has.  Create a shortcut to the Zune.exe file, edit the properties of the shortcut and add &lt;b&gt;-animations:false&lt;/b&gt; to the end of the command line.
&lt;/p&gt;

&lt;p&gt;
That was nice, but you still have some issues, so you want to drop DirectX and go with a straight GDI application.  I don&amp;#39;t know much about Vista, but I have a nagging thought that Vista did away with GDI, so if you&amp;#39;re on Vista, I don&amp;#39;t know what will happen.  So you create the shortcut and add &lt;b&gt;-gdi&lt;/b&gt; to the end of the command line.
&lt;/p&gt;

&lt;p&gt;
You want to mess around with some of the other settings (which I don&amp;#39;t really see as valuable)? Go ahead, knock yourself and your computer out.
&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=222" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry><entry><title>Workplace Cruelty</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/03/08/workplace-cruelty.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/03/08/workplace-cruelty.aspx</id><published>2008-03-08T02:03:00Z</published><updated>2008-03-08T02:03:00Z</updated><content type="html">&lt;p&gt;
Back in a previous job, we had technical interviews for prospective employees.  I went through one myself and it was tough.  I was sure I bombed it, because one guy found a weak spot in my knowledge and kept drilling into it.  As it turns out, I did ok and they hired me.
&lt;/p&gt;
&lt;p&gt;
In a year&amp;#39;s time I had climbed the ranks and suddenly found myself doing technical interviews on the other side of the desk.  One of the things that I was tasked with was writing better technical questions for .NET programmers and analysts.  I and the coder types I gathered with at work all pitched in make a great tech interview to be given over the phone before bringing in the candidate for a face-to-face.
&lt;/p&gt;
&lt;p&gt;
Once I started doing the interviews, I discovered just how poor the pool of available talent was.  I guess it might have been more a reflection on the headhunters sending us the candidates.  But sometimes I thought I was asking a little much with some of the questions.  I&amp;#39;m not going to divulge the questions, but I want to discuss one of them because it is pretty interesting.  It&amp;#39;s also the most devious.  I only found one person who could answer it correctly.  And to be fair, I couldn&amp;#39;t have answered it myself.
&lt;/p&gt;
&lt;p&gt;
And by the way, if you have the opportunity to cheat on a phone interview.  For example, someone you know inside the company finds the document containing all the questions and answers and distributes it to your consulting company or just to friends.  Don&amp;#39;t be an idiot.  We know when you are cheating.  I had one case of blatant cheating where the answers given back to me were nearly word for word what was in my Q&amp;amp;A spreadsheet.  The sad part was, we brought the person in for a face-to-face interview and asked questions from an alternate question pool (one that wasn&amp;#39;t in a document on the network) and her skills were fine.  She didn&amp;#39;t even need to cheat.
&lt;/p&gt;
&lt;p&gt;
But anyways, the trick question.  The question was asking the difference between ByVal and ByRef and how they apply to classes and structures.  There is a difference and those that didn&amp;#39;t know it but tried to be confident when giving their answers were completely demoralized when asked to describe the difference.
&lt;/p&gt;
&lt;p&gt;
If you&amp;#39;ve done any MCSA/MCSD certification training, you may recall this topic is discussed.  I remember it from my training, but I also remember thinking at the time &amp;quot;who cares?&amp;quot;  It can have consequences if you don&amp;#39;t pay attention to it.  It&amp;#39;d probably be one of those bugs that after days of research you&amp;#39;d share with your peers: &amp;quot;Hey, did you know...&amp;quot;
&lt;/p&gt;
&lt;p&gt;
So here&amp;#39;s the trick: There is no ByVal when you are passing a class to a method.  There is only ByRef.  So if you pass a class to a method using ByVal, you are working on the original class, not a copy.  If you pass a structure to a class ByVal, you are working on a copy.  You can pass a structure ByRef and you will work on the original.
&lt;/p&gt;
&lt;p&gt;
Why?  Because of the way .NET allocates memory.  There is the Stack and the Heap.  The Stack is small and efficient, the Heap is big and disorganized.  but the Heap can hold lots of stuff.  The stack is reserved for value types - small data structures like Booleans and Integers - while the Heap holds big things like Strings and Classes.  A Structure is a value type even though it can have properties and methods like a class.  A class is an Object type, and all objects go on the heap.
&lt;/p&gt;
&lt;p&gt;
Since classes are big, when you pass a class to a method, it only sends a pointer to the class of where the instance of the class is on the heap, AKA, a reference, By Reference, ByRef, even though it says ByVal, it&amp;#39;s not true.
&lt;/p&gt;
&lt;p&gt;
But, but, what if a class has a structure as a property?  And what if a structure has a class as a property?  When does it reference it and when does it copy it?  Well, let&amp;#39;s see.
&lt;/p&gt;
&lt;p&gt;
Make a class and a structure with the opposite inside each:
&lt;/p&gt;
&lt;p&gt;&lt;pre&gt;
Public Class WithStruct
    Public struct As InsideStructure
    Public text As String
    Public number As Integer

    Public Structure InsideStructure
        Public text As String
        Public number As Integer
    End Structure

End Class

Structure WithClass
	Public cl As WithStruct
	Public text As String
	Public number As Integer
End Structure
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;
Make some methods to modify the guts:
&lt;/p&gt;
&lt;p&gt;&lt;pre&gt;
Private Sub ModifyInternals(ByVal obj As WithStruct)
	obj.text = &amp;quot;Modified&amp;quot;
	obj.number = -1
	obj.struct.text = &amp;quot;Inner modified&amp;quot;
	obj.struct.number = -10
End Sub

Private Sub ModifyInternals(ByVal obj As WithClass)
	obj.text = &amp;quot;Modified&amp;quot;
	obj.number = -1
	obj.cl.text = &amp;quot;Inner modified&amp;quot;
	obj.cl.number = -10
End Sub
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;
Make the objects and call them and look at the results:
&lt;/p&gt;
&lt;p&gt;&lt;pre&gt;
Structure (before and after):
Text:The text, Number:1, InnerText:Inside text, InnerNumber:10
Text:The text, Number:1, InnerText:Inner modified, InnerNumber:-10

Class (before and after):
Text:The TEXT, Number:2, InnerText:Inside TEXT, InnerNumber:20
Text:Modified, Number:-1, InnerText:Inner modified, InnerNumber:-10
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;
Summary: The structure maintained its original values, but the class inside the structure was modified.  The class was modified and so was its internal structure.
&lt;/p&gt;
&lt;p&gt;
Is your head spinning yet?  Good.
&lt;/p&gt;
&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=221" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry><entry><title>Read the Zune Collection in .NET from Zune's own API</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/03/03/read-the-zune-collection-in-net-from-zune-s-own-api.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/03/03/read-the-zune-collection-in-net-from-zune-s-own-api.aspx</id><published>2008-03-03T02:26:00Z</published><updated>2008-03-03T02:26:00Z</updated><content type="html">&lt;p&gt;
I was installing the latest version of the Zune software and actually read a bit of the license agreement.  This line caught my eye:
&lt;/p&gt;
&lt;p&gt;
&lt;blockquote&gt;
&lt;i&gt;Distributable Code. The software contains code that you are permitted to distribute in programs you develop if you comply with the terms below.&lt;/i&gt;
&lt;/blockquote&gt;
&lt;/p&gt;
&lt;p&gt;
Oh, really?  Programs that I develop?  This reinforced a suspicion I had that there was a usable API in the Zune software.  And there is.  It is ZunedbAPI.dll.  I don’t know much about it, but I do know how to read the Zune collection (formerly known as the library).  It&amp;#39;s as simple as adding a reference to that DLL, found in the Zune program folder.  A pre-caveat: There are dependancies with this DLL, so you can either run your custom app in the Zune folder, or you can use trial and error to find out which DLLs are needed.  I chose the former out of convenience.  
&lt;/p&gt;
&lt;p&gt;
So what are some of the objects you’re going to be dealing with to read the library?  There’s the MicrosoftZuneLibrary namespace and in it are some objects you will learn to know:
&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;ZuneLibrary&lt;/li&gt;
	&lt;li&gt;ZuneQueryList&lt;/li&gt;
	&lt;li&gt;ZuneQueryItem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
ZuneLibrary is the start of everything.  But just creating an instance of it will not do anything.  You also need to call the Initialize method on it:
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
Dim zuneLib As ZuneLibrary
zuneLib = New ZuneLibrary
zuneLib.Initialize()
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
And you MUST clean up after yourself.  These objects are very sensitive to being left hanging and when the GC comes along, it’s going to throw up all over your program.  So always call Dispose when you are done with it.  Never just let it fall out of scope.
&lt;/p&gt;
&lt;p&gt;

So you now have a connection to the Zune collection.  The queries are a little bit limiting; there’s nothing free-form about them, but you can use them to get the raw data and work it from there.  There are methods like:
&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;QueryDatabase&lt;/li&gt;
	&lt;li&gt;GetAlbumsByArtists&lt;/li&gt;
	&lt;li&gt;GetTracksByAlbum&lt;/li&gt;
	&lt;li&gt;GetTracksByPlaylist&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
And others for you to discover.  These methods take some parameters that might need explaining.   Once one is explained, you should be able to apply that logic to the others.  Let’s look at the first one: QueryDatabase.  Its signature is:
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
Public Function QueryDatabase(ByVal QueryType As EQueryType, 
	ByVal LibraryView As Integer, ByVal SortType As EQuerySortType, 
	ByVal SortAtom As UInteger, 
	ByVal propertyBag As MicrosoftZuneInterop.QueryPropertyBag) 
	As MicrosoftZuneLibrary.ZuneQueryList
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
The first parameter is an enum.  That makes it easy to pick a query type.  Look at some of the choices:
&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;EQueryType.eQueryTypeAllAlbums&lt;/li&gt;
	&lt;li&gt;EQueryType.eQueryTypeAllPhotos&lt;/li&gt;
	&lt;li&gt;EQueryType.eQueryTypeAllTracks&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
I’m kind of sticking to these, because the others probably have parameters taht need to be sent in a PropertyBag and I haven’t worked them out yet.  So the easy example is to list all albums.  Pick the proper enum and continue.
&lt;/p&gt;
&lt;p&gt;
The next parameter is the library view.  I’ve not found this to work with anything but zero.  Then in the next parameter you specify the sort type.  It’s an enum and doesn’t need explanation.
&lt;/p&gt;
&lt;p&gt;
The next to last parameter refers to an “atom”.  This is a Uint value for a column.  There’s no indication of this, but the atoms are listed in the enum: SchemaMap.  The difficult thing is figuring out which atoms apply to which file types.  I have a bit of code at the end of this post to help with that.
&lt;/p&gt;
&lt;p&gt;
So you need to choose which column you want to sort by by using the value from the SchemaMap enum.  If you pick an atom that isn’t valid, your call will error out.  It’s pretty rough.  You can always specify zero and it doesn’t seem to care.
&lt;/p&gt;
&lt;p&gt;
Last property is the PropertyBag.  This is important for some queries for sure, but I haven’t taken the time to figure out how to instantiate one and put the values into it.  So for now, using Nothing is the proper value.
&lt;/p&gt;
&lt;p&gt;
The query will come back into a ZuneQueryList object.  Or will be Nothing if the query failed.  Like if you set an invalid library view value.
&lt;/p&gt;
&lt;p&gt;
What’s this look like in code?  Here’s a query for all artists:
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
Dim artists As MicrosoftZuneLibrary.ZuneQueryList
artists = zuneLib.QueryDatabase(EQueryType.eQueryTypeAllAlbumArtists, 
	0, EQuerySortType.eQuerySortOrderAscending, 
	CUInt(MicrosoftZuneLibrary.SchemaMap.kiIndex_DisplayArtist), Nothing)
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
Not bad.  Now, how to get at the stuff inside the QueryList?  It doesn’t have any Item property.  It does have a Count property, so you could loop through it, but how do you get the fields?
&lt;/p&gt;
&lt;p&gt;
The answer is the GetFieldValue function.  Let’s see one of its signatures (it’s overloaded):
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
Public Function GetFieldValue(ByVal index As UInteger, 
    ByVal type As System.Type, ByVal Atom As UInteger) As Object
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
Seems pretty straightforward, the Index is the index of the item you want, the type is the datatype you expect, and the atom is, well, an atom.  Using the SchemaMap enumeration, this is easy.
&lt;/p&gt;
&lt;p&gt;
There is another way to get an item, and that is using the ZuneQueryItem object.  You instantiate it using a query list and an index.  Once you have a ZuneQueryItem, you can use the GetFieldValue function on it, which has a similar syntax, obviously missing the index parameter.
&lt;/p&gt;
&lt;p&gt;
Let’s see that in code.  I have a listbox called lstArtists and a custom class that holds the ID and name of the object (overriding the ToString method to display the name):
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
For i As Integer = 0 To artists.Count - 1
	lstArtists.Items.Add(CStr(artists.GetFieldValue(CUInt(i), 
		GetType(String), 
		CUInt(MicrosoftZuneLibrary.SchemaMap.kiIndex_DisplayArtist), &amp;quot;&amp;quot;))
Next
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
Or maybe the other way, when you select an item:
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
Dim i As MicrosoftZuneLibrary.ZuneQueryItem
i = New MicrosoftZuneLibrary.ZuneQueryItem(artists, lstArtists.SelectedIndex)
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
That’s it.  You can now query the Zune collection!  Always be sure to clean up after yourself.  
&lt;/p&gt;
&lt;p&gt;
Now, here’s that code that I said is helpful for finding out the atoms on an object.  Create a form with a DataGridView and add this method.
&lt;/p&gt;
&lt;p&gt;
Set up your main code to perform a query and get a ZuneQueryItem from the results.  Then create the display form and pass that QueryItem to this method.
&lt;/p&gt;
&lt;p&gt;
The method:
&lt;/p&gt;
&lt;p&gt;
&lt;pre&gt;
Public Sub ShowItem(ByVal i As MicrosoftZuneLibrary.ZuneQueryItem)
    Dim val As String
    
    For Each v As MicrosoftZuneLibrary.SchemaMap In 
    	[Enum].GetValues(GetType(MicrosoftZuneLibrary.SchemaMap))

        val = CStr(i.GetFieldValue(GetType(String), CUInt(v)))
        If val Is Nothing Then val = CStr(i.GetFieldValue(GetType(Date), CUInt(v)))
        If val Is Nothing Then val = CStr(i.GetFieldValue(GetType(Integer), CUInt(v)))
        If val Is Nothing Then val = CStr(i.GetFieldValue(GetType(Guid), CUInt(v)))
        dgFile.Rows.Add([Enum].GetName(GetType(MicrosoftZuneLibrary.SchemaMap), v), val)
    Next

    Me.Show()

End Sub
&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;
If anyone finds out anything further about the Zune API, I am found on &lt;a href="http://www.zuneboards.com/forums/members/anachostic.html"&gt;ZuneBoards&lt;/a&gt;.  Look me up there.
&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=216" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry><entry><title>A Flickr code sample (free hypocrisy included)</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/02/24/a-flickr-code-sample-free-hypocrisy-included.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/02/24/a-flickr-code-sample-free-hypocrisy-included.aspx</id><published>2008-02-24T03:16:00Z</published><updated>2008-02-24T03:16:00Z</updated><content type="html">&lt;p&gt;
So, I was working with a Flickr photoset with thousands of pictures and
one day it was decided: &amp;quot;Let&amp;#39;s redo the tags to be more descriptive.&amp;quot;  Now, if
you use Flickr, you know it&amp;#39;s got a pretty neat web interface, but web applications
just aren&amp;#39;t really meant for certain things like bulk operations.  It would be
better to have an offline application that could update the photos.  So I created
rTagger.
&lt;/p&gt;

&lt;p&gt;
That&amp;#39;s not the subject of this post. So, I was writing this program to handle Flickr
tags and save them.  Now, if you&amp;#39;ve written applications for
Flickr, you know it&amp;#39;s got a great .NET API, but some APIs still have you go through
a bunch of steps to work with it, and Flickr&amp;#39;s API was no different.  So i created
a class to make it more simple.
&lt;/p&gt;

&lt;p&gt;
That&amp;#39;s the subject of this post.  I was just trying to think of ideas to post and this 
one came up.  So here you go, the FlickAppAuth class.  It uses a Singleton pattern
(woo hoo)... kind of.  It manages the state of the Flickr object, but really it&amp;#39;s a 
little dumb in that it could return Nothing.  Looking at my previous posts about 
intelligent objects makes this post seem a little hypocritical, but if you&amp;#39;ve been
taking notes, you should know just how to improve it on your own.
&lt;/p&gt;

&lt;p&gt;
So if it&amp;#39;s so dumb, what does it do?  It basically reduces the code you have to write,
puts it all in one place, and gives you a class to copy between projects.  There&amp;#39;s a 
couple things the class does for you: Authorization (with persistance) and Deauthorization.
Pretty much what you would expect by its name.
&lt;/p&gt;

&lt;p&gt;
So if you wanted auth an application, you would use code like:
&lt;/p&gt;

&lt;p&gt;
&lt;pre&gt;
If Not FlickrAppAuth.IsFlickAuthorized Then
    MsgBox(&amp;quot;You must authorize this application with Flickr.&amp;quot;)
    FlickrAppAuth.AuthorizeApp()
Else
...
End If
&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;Too much code?&lt;/p&gt;

&lt;p&gt;
Then you can use the Flickr object out of the auth object
&lt;/p&gt;

&lt;p&gt;
&lt;pre&gt;
Dim f As FlickrNet.Flickr

f = FlickrAppAuth.Flickr
&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;
Now, the dumb part that I alluded to above is that you have to call the FlickrAppAuth.IsFlickAuthorized
method once before trying to get the FlickrNet.Flickr object, otherwise it will be Nothing.  I suppose you could
call it in the property the first time, but then if it&amp;#39;s not authorized, you have to
do something about it.  Do what?&amp;gt;  Throw a custom exception?  Return Nothing and test
for it back in the main app?  I figured what I had was a decent compromise.
&lt;/p&gt;

&lt;p&gt;So here&amp;#39;s the code...&lt;/p&gt;

&lt;p&gt;
&lt;pre&gt;
Public Class FlickrAppAuth
    Private Shared flickrApp As FlickrNet.Flickr
    Private Shared flickrAuth As FlickrNet.Auth
    Private Shared flickrFrob As String
    Private Shared flickrToken As String

    &amp;#39; rTagger key for Anachostic
    Private Const FLICKR_KEY As String = &amp;quot;&amp;quot; &amp;#39; Get your own
    Private Const FLICKR_SECRET As String = &amp;quot;&amp;quot; &amp;#39; Get your own

    Public Shared ReadOnly Property Flickr() As FlickrNet.Flickr
        Get
            Return flickrApp
        End Get
    End Property

    Public Shared ReadOnly Property UserID() As String
        Get
            Return flickrAuth.User.UserId
        End Get
    End Property

    Shared Sub New()
        flickrToken = My.Settings.FlickrToken &amp;#39; Or use your own storage scheme

    End Sub

    Public Shared Sub AuthorizeApp()
        Dim flickrUrl As String

        &amp;#39; Get Frob    
        flickrApp = New FlickrNet.Flickr(FLICKR_KEY, FLICKR_SECRET)
        flickrFrob = flickrApp.AuthGetFrob()

        &amp;#39; Calculate the URL at Flickr to redirect to
        flickrUrl = flickrApp.AuthCalcUrl(flickrFrob, FlickrNet.AuthLevel.Write)

        &amp;#39; Load the URL in the default browser.
        System.Diagnostics.Process.Start(flickrUrl)

    End Sub

    Public Shared Sub DeAuthorizeApp()
        My.Settings.FlickrToken = &amp;quot;&amp;quot;
        flickrApp = Nothing
        flickrAuth = Nothing
        flickrFrob = Nothing
        flickrToken = Nothing
    End Sub


    Public Shared Function IsFlickAuthorized() As Boolean
        Try
            &amp;#39; Authorize app
            If flickrApp Is Nothing Then
                flickrApp = New FlickrNet.Flickr(FLICKR_KEY, FLICKR_SECRET)
            End If

            If flickrFrob Is Nothing Then
                flickrFrob = flickrApp.AuthGetFrob()
            End If

            &amp;#39; If we have a cached token, use it
            If flickrToken &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then
                flickrAuth = flickrApp.AuthCheckToken(flickrToken)
                flickrApp = New FlickrNet.Flickr(FLICKR_KEY, FLICKR_SECRET, flickrAuth.Token)

            Else
                &amp;#39; get a new token (assuming we authed the app already)
                flickrAuth = flickrApp.AuthGetToken(flickrFrob)
                flickrApp.AuthToken = flickrAuth.Token
                flickrToken = flickrAuth.Token
                My.Settings.FlickrToken = flickrToken

                flickrApp = New FlickrNet.Flickr(FLICKR_KEY, FLICKR_SECRET, flickrAuth.Token)

            End If

            Return True

        Catch ex As FlickrNet.FlickrException
            Return False

        Catch ex As Exception
            Return False

        End Try

    End Function

End Class

&lt;/pre&gt;
&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=210" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry><entry><title>Still kickin'</title><link rel="alternate" type="text/html" href="http://soapitstop.com/blogs/fleamarket/archive/2008/02/20/still-kickin.aspx" /><id>http://soapitstop.com/blogs/fleamarket/archive/2008/02/20/still-kickin.aspx</id><published>2008-02-20T02:57:00Z</published><updated>2008-02-20T02:57:00Z</updated><content type="html">&lt;p&gt;
You know what?  I &lt;i&gt;am&lt;/i&gt; going to redo my ANSI project.  I tested out a couple things and the .NET 2.0 console additions do away with all the crappy Win32 API calls I had to do.  So now the basic plan if to have some objects like Form, Label, TextBox, MsgBox, and whatever else.  Obviously the forms will store their own state in their child controls.  You should be able to overlay, show and hide them.
&lt;/p&gt;
&lt;p&gt;
In the brief test I did, I have a Form object and a Label control.  The Form object has an assignable border.  See?
&lt;/p&gt;
&lt;img src="http://www.700cb.net/images/blog/ansi1.gif" alt="" /&gt;

&lt;p&gt;The code is pretty manual right now, but I&amp;#39;ll clean that up eventually.  Maybe I&amp;#39;ll even learn how to create a Designer for Visual Studio!&lt;/p&gt;

&lt;p&gt;&lt;pre&gt;
Dim f As New ANSIForms.Form
Dim l As ANSIForms.Label

l = New ANSIForms.Label
With l
	.Text = &amp;quot;Welcome to ANSIForms&amp;quot;
	.ForeColor = ConsoleColor.Yellow
	.Location = New Drawing.Point(15, 2)
End With
f.Controls.Add(l)

l = New ANSIForms.Label
With l
	.Text = &amp;quot;This is going to be alot of fun, I can tell&amp;quot;
	.ForeColor = ConsoleColor.Cyan
	.Location = New Drawing.Point(8, 4)
End With
f.Controls.Add(l)

l = New ANSIForms.Label
With l
	.Text = &amp;quot;Labels work, now to do textboxes and create an ActiveControl concept.&amp;quot;
	.ForeColor = ConsoleColor.Cyan
	.Location = New Drawing.Point(2, 5)
End With
f.Controls.Add(l)

l = New ANSIForms.Label
With l
	.Text = &amp;quot;wait, I need to make labels handle text wrapping and honor the size property.&amp;quot;
	.ForeColor = ConsoleColor.DarkYellow
	.Location = New Drawing.Point(2, 5)
End With
f.Controls.Add(l)

f.Show()


Console.CursorLeft = 10
Console.CursorTop = 10

Console.ReadLine()

&lt;/pre&gt;&lt;/p&gt;&lt;img src="http://soapitstop.com/aggbug.aspx?PostID=209" width="1" height="1"&gt;</content><author><name>anachostic</name><uri>http://soapitstop.com/members/anachostic.aspx</uri></author></entry></feed>