Thursday, May 08, 2008 8:00:07 PM UTC #

A while back I came across this direct comparison of MediaWiki, the wiki engine powering Wikipedia, and SharePoint's built-in wikis.

As you might imagine, the comparison favored MediaWiki. And, as I left an embarrassingly passionate comment rebuttal (in which I link directly back to this address), I feel compelled to write the following post.

Summary first: because I meander quite a bit

The summary is: you probably don't need MediaWiki's extensive featureset for your corporate intranet. Assuming limited needs, SharePoint's wikis are a great, no-maintenance, small-learning curve solution to the "informal team wiki" problem. You can do better feature-wise, but why would you want to? Plus, you already have SharePoint—this is a no-brainer.

Well, let's get with the details.

Wiki syntax: unnecessary

So, let me start off by saying I hate wiki syntax. Actually I need to clarify: I hate any markup syntax built on top of HTML, and that includes MediaWiki's wiki syntax, the FlexWiki syntax I've used, whatever syntax ScrewTurn Wiki uses (it's different from FlexWiki), and the perennial favorite, [BBcode] markup. I hate all this for two reasons:

  1. It's annoying to learn a new syntax for bolding up a word when <strong></strong> works just fine in HTML thank you, and
  2. It's totally unnecessary.

We are now presented with the question: but Peter, what alternative do we have?

Just use HTML

Just use HTML! Allow me clarify in the next section:

You can parse the input and allow only a subset of HTML

I'm not saying to throw wide the gates and allow everything. It's perfectly reasonable to parse input and allow only specific markup, negating any and all security concerns! And when I say "parse", I don't mean some kind of abomination involving string.Replace() or even regex.Replace().

So if someone types: "Hey, I like to <strong>bold me up some text!</strong><script><!— some nasty js virus bomb —></script>", you know what? You can figure that out! Don't just give up and say "oh forget it, let's just change the <b> to [b] and make our 1 billion users learn it." You know what? YOU CAN FIX IT, DON'T GIVE UP! 

It's possible; look into it—it's better than inventing Yet Another Markup Language. [[Insert your own awesome YAML joke here!! Ha ha, good one!]]

Back to wikis

So with Peter's Fundamental Law #14 ("Don't invent yet another YAML") out of the way, let's get back to the comparison.

It's all about context

What are you looking for in a wiki—are you attempting to build "wikipedia for my global enterprise"? If so…I don't actually believe anyone's attempting to do this. Leave me a comment if you are, and if you have implemented MediaWiki in a corporate environment to accomplish this goal. There probably are people attempting to do this, which is fine. I haven't met them, but I'm sure they're out there. Maybe.

But I'm here today to tell you that most of you don't need MediaWiki. You may think you do, but if you actually go out and talk to some of your users, you'll find out: you don't. Your corporation is not filled with anonymous trolls—the trolls are still around, but [[insert your own boss joke here]]. Ow, my sides!

Anyway, MediaWiki is built to work with the semi-anonymous internet, and on a massive scale. You, on the other hand, have a grand total of 30 people in your enterprise who are clued into the fact that the mouse sitting on their desk has a right mouse button, and have a solid understanding of how a folder can contain other folders, and files. There's 30 of you.

The corporate intranet is not the same as the raw, unfiltered wilderness of crazy that is the internet.

What crazy world do you live in anyway

Let's just state this as a fact: your IT department does not have linux admins. Or if they do, they're hidden so well you may not recognize them. The point being: when you ask someone to install MediaWiki, you'll be asked: does this thing run on Server 2003, or does it require Server 2008? Um, gusty* gibbon or newer? That sort of answer will not register; please try again.

Oh, and while we're talking corporate IT politics, you may want to avoid using the words "Open Source" or "free" or "third-party" or "custom" or pretty much anything. Also, try and somehow pretend MediaWiki is made by Microsoft. If you say the wrong word, or fail to say the correct ones, you may alert your IT group to the fact that this software is unapproved!

* this is hilarious, think about it

Who becomes the admin?

Something else to keep in mind: if IT actually goes off and actually installs the thing, how are you ever going to get access to it? If you haven't learned by now, the easiest application to support is the one with the fewest users. And a good approach to keeping your user count down is to prevent them from crowding in too much in the first place. Zero is the best number!

SharePoint Time

Let's get down to business: actually comparing SharePoint's wikis to MediaWiki, head to head. I'll take the SharePoint perspective:

SharePoint PROS:

  • SharePoint wikis take a grand total of two minutes to install and configure. Two minutes.
    • Infrastructure concerns, like high availability and security, are covered.
    • As Don King would say, it's "supportatudinous!" IT supports it already! It is backed up like the rest of the SharePoint data! You'll get upgrades for free!
    • You didn't even have to fill out the 8 page online help desk form, followed by a 10 page project request form, followed by a 3 page departmental project request form, followed by 2 security forms, followed by a third "surprise!" security form. You just made the wiki, all by yourself! Like a grownup! It was so simple I didn't even have to use fancy words like "provision"!
  • SharePoint wikis use Integrated Windows Authentication*, emphasis on the word Integrated. The point is: seamless security. Footnote: configurable, maybe you're not using Integrated Windows Authentication specifically.
  • SharePoint wikis have minimal wiki syntax, instead relying on the rich text edit control. What's the syntax to bold up some text? Oh yeah, click the bold icon. Awesome.

SharePoint CONS:

  • SharePoint wikis are relatively feature-thin. I'm totally okay with this, but I'm sure the grizzled internet wiki veteran will be angered by, for example, SharePoint's extremely easy-to-delete pages, and lack of discussion pages, etc.
  • SharePoint wikis are lists, and as such, should probably remain smaller than 2000 items. Yeah, there's a whitepaper on the subject; after too many items, performance of operations on a list slows to a crawl.
  • SharePoint costs money, somewhere down the line—either for SharePoint itself, or for SQL Server, or just the server license, SOMEWHERE down the line, you're paying.

Intranet NOT Internet

If there's one thing you get through your skull—actually, if there's one thing, let's make it Peter's Fundamental Law #14 ("Don't invent yet another YAML")—okay, let's try for two things. If we have room for two things, the second one should be: the intranet is not the same as the internet. When comparing wiki engines, keep this in mind! The intranet is not the same as the internet!

Categories: SharePoint
Technorati:
Thursday, May 08, 2008 8:00:07 PM UTC  #     |  Comments [0]  |  Trackback
Monday, May 05, 2008 8:00:29 PM UTC #

I just fixed an odd 403.14 server error on my Server 2008 VM, and what was the problem? My application was set to the "DefaultAppPool" app pool. The cause? "DefaultAppPool" doesn't exist, and yet my web site is somehow set to run on "DefaultAppPool". "DefaultAppPool" didn't event exist at the time I created the web application in IIS, much less now. By all means this should not have been a problem—IIS should set newly provisioned web sites to an existing, non-imaginary app pool—yet it was a problem.

So, advice: don't delete the default app pool, even in the new hotness that is IIS 7 and Windows Server 2008. You certainly can do so—I'm not saying it's impossible to get along without the default app pool; I'm just saying that you'll have surprises. And not the "congratulations, it's the prize patrol" type surprises, more like the "congratulations, your vehicle has been towed!" surprises.

You don't have to take my word for it—instead listen to Joel Oleson (talking about IIS6), and I quote:

Default Application pool

Just leave it alone, don't use it, and occasionally make sure nothing is using it.  Do NOT delete it.  Why… Cause IIS doesn't like it when it doesn't exist.  You'll find IIS gets mad if this gets deleted.  Even if you plan to never use it, just leave it alone.  Don't even rename it.  You can put something funny in the description field to remind you, but as was the unspoken best practice in the IIS 4 and IIS 5 days with the default web site.  Only newbies use it, the more experienced web admins create new web apps and stop or deleted it.  Now I'm saying though you may want to delete it. Don't.

Categories: .NET | SharePoint
Technorati:  | 
Monday, May 05, 2008 8:00:29 PM UTC  #     |  Comments [1]  |  Trackback
Friday, May 02, 2008 8:00:26 PM UTC #

speed_2Pop quiz, hotshot: how do you double your SharePoint farm's searching speed?

(scroll down for the secret answer! If you have a large or otherwise high-resolution monitor, pretend you have tunnel vision!)

.

.

.

.

.

.

.

.

.

Do you need a hint?

.

.

.

.

.

.

.

.

TRICK ANSWER: Switch to an alternative browser! Instant speed boost!

image

I'm not trying to start a fight

I've been working with SharePoint's search recently, and have come away duly impressed by its capabilities. Today I'm highlighting yet another positive aspect of SharePoint's Enterprise Search—the fact that it is incredibly fast, and faster than you probably think—and at the same time, maybe stomping a little on IE. Just a little.

The point is, a lot of the time you spend waiting for search results on a SharePoint portal is spent by IE rendering the page, not by the SharePoint server. So, okay, what does this mean, and why do I care?

Takeaways - what to do about it

  • Keep in mind, as an option, that the SharePoint search web service exists, and is a perfectly good way to serve up search requests on your other (non-SharePoint) portal. And it's fast.
  • If you're demoing SharePoint, and especially as a Web Content Management tool, then by all means use the fastest browser available. If you're trying to show off SharePoint's capabilities, show them how fast it runs a search! But don't settle for IE's speeds. SharePoint is unfairly perceived as an "always slow" application, and we need to try and break that perception. Yes, it can be slow; no, it doesn't have to be slow. It can be quite snappy, believe it or not.
  • Note also, that you don't need to load most of what's on a SharePoint search results page. I've been digging into a MS-PL (thank you!)-licensed Search Center branding project on CodePlex, and I'm amazed at how much cruft we can remove without losing anything. It should go without saying, but: the more you remove, the faster the page is served up, and the faster the browser renders. Win-win! Trim that search page! Take a chainsaw to it!
Categories: SharePoint
Technorati:
Friday, May 02, 2008 8:00:26 PM UTC  #     |  Comments [0]  |  Trackback
Thursday, May 01, 2008 4:34:40 AM UTC #

I've updated my hotter-than-hot SharePoint search page, and let me tell you: it's hot!

Here are four reasons my search page is hotter than ever:

  1. I've added Google Reader search to the mix! If, like me, you learn most about SharePoint from your blogroll, then it shouldn't surprise you to discover that searching Google Reader will return the absolute best results. Try it for a while and you'll agree! If you don't have a blogroll to search, borrow mine!
  2. I've swapped the newsgroups search over to https://groups.google.com/ and instructed it only to search the microsoft.public.sharepoint.* groups. Google Groups search works more consistently (as in uptime) than Microsoft's Communities page search—bottom line, I can't trust the results from the MS Communities search page.
  3. In-browser HOTKEYS! Believe it! They even work!
  4. My page loads instantly! If you're doing the math, comparing this to any other page is a divide by zero error! NaN! My page is NaN faster!

image

Mission statement

The SharePoint search page is something I created for my personal use, and which I use daily, to search for SharePoint-related content, whether I'm looking for broad overviews, deep technical solutions, or looking for similar cries for help while troubleshooting.

While most people are satisfied to search Google or Live.com or whatever, I am not. Were it in my power, I would combine Google Search (or Live.com search; it's not bad)—anyway, I would combine whatever search with the complete Technet Forums content and complete Usenet archives; then rank the good weblogs higher; then somehow crawl MSDN's buried whitepapers. And then be done with it. That's my dream.

Until that magical day, however, the SharePoint search page will have to suffice.

Get at it!

http://www.pseale.com/SharePoint/search/

Categories: SharePoint
Technorati:
Thursday, May 01, 2008 4:34:40 AM UTC  #     |  Comments [0]  |  Trackback
Wednesday, April 23, 2008 10:56:08 AM UTC #

Update: welcome to the new-and-improved recap! This recap, unlike the last, weighs in at less than a million billion byes of text and code highlighting and will now load in your feed reader.

This is a recap of my entries into the 2008 Winter Scripting games. From, like, the winter. I know, it's April, we're already in summertime mode here in Texas, and it is quite clear that it is no longer 'the winter'. Let's move on, shall we?

I'm going to work through each of the following scripts illustrated in the table below (the counts for "Lines", "Words", and "Characters" mean what you would imagine they mean):

image

Compare the above table to MOW, who, for example, had a 1 line, 8 word, 58 character solution for #6. My solutions are (relatively) HUGE. So my recaps, which contain the full source, will necessarily be HUGE as well.

For each problem, I'm going to quickly sum up the interesting (at least TO ME) bits of each problem, then I'm going to post the full source.

2008 Winter Scripting Game Events: Index

Categories: Awesomeness | PowerShell
Technorati:  | 
Wednesday, April 23, 2008 10:56:08 AM UTC  #     |  Comments [0]  |  Trackback
Wednesday, April 23, 2008 3:47:17 AM UTC #

If you aren't already in the know, these ten problems are from the 2008 Winter Scripting games.

For each problem, I'm going to quickly sum up the interesting (interesting TO ME) bits of each problem, then I'm going to post the full source.

Event 10: Blackjack!

Here we are asked to simulate a text-based Blackjack game. Mine works, I'm certainly not proud of the graphics, not proud of the colors, not even necessarily proud of the structure of my solution.

Please do not look at any of the following code and think "that's how I'm supposed to use objects in PowerShell!" Please don't. It's NOT ideal, I made several design mistakes; I don't even think most of my objects are necessary. Or, thinking from the other side—maybe I didn't go far enough.

Source

#PROBLEM #10
$cardValues = @{
    "Ace" = 11;
    "King" = 10;
    "Queen" = 10;
    "Jack" = 10;
    "Ten" = 10;
    "Nine" = 9;
    "Eight" = 8;
    "Seven" = 7;
    "Six" = 6;
    "Five" = 5;
    "Four" = 4;
    "Three" = 3;
    "Two" = 2;
}


$suits = @("Spades", "Hearts", "Diamonds", "Clubs")


#bad random number generator
$rnd = new-object Random




function Create-DeckObject
{
    $o = new-object PSObject
    $cards = @()
    foreach ($suit in $suits)
    {
        foreach ($cardValue in $cardValues.Keys)
        {
            $cards += Create-CardObject -value $cardValue -suit $suit
        }
    }
   
    $sortedDeck = $cards | sort PositionInDeck
   
    Add-Member -inputObject $o -memberType NoteProperty -name "Cards" -value $sortedDeck
    Add-Member -inputObject $o -memberType ScriptProperty -name "Deal" -value { $nextCard = $this.Cards | select -first 1; $this.Cards = $this.Cards | select -last ($this.Cards.Count - 1); $nextCard }
   
    $o
}


function Create-CardObject ($value, $suit)
{
    $o = new-object PSObject


    Add-Member -inputObject $o -memberType NoteProperty -name "Card" -value ("$value of $suit")
    Add-Member -inputObject $o -memberType NoteProperty -name "BlackjackValue" -value $cardValues[$value]
    Add-Member -inputObject $o -memberType NoteProperty -name "PositionInDeck" -value $rnd.NextDouble()
   
    $o
}


function Create-HandObject ([switch]$isdealer)
{
    $o = new-object PSObject


    $emptyHand = @()
    Add-Member -inputObject $o -memberType NoteProperty -name "Cards" -value $emptyHand
    Add-Member -inputObject $o -memberType NoteProperty -name "IsDealerHand" -value $isdealer


    #this value will change for the dealer hand as the game progresses.
    Add-Member -inputObject $o -memberType NoteProperty -name "AreAllCardsRevealed" -value (-not $isdealer)
    Add-Member -inputObject $o -memberType ScriptProperty -name "BlackjackValue" -value { $total = 0; $this.Cards | % {$total += $_.BlackjackValue}; $total }
   
    $o
}


function Print-VisibleCards ($cards,$allcardsvisible,[switch]$isdealer)
{
    $output = @()
    if ($allcardsvisible -eq $TRUE)
    {
        foreach ($card in $cards)
        {
            $output += $card.Card
        }


        #POSTSCRIPT-OOPS! Looks like I'm calculating the "total value of hand", when
        #I expose that value as a script property! This function would have been
        #IDEAL as a ScriptMethod attached to the Hand object.
        $total = 0; $cards | % { $total += $_.BlackjackValue }
        if (-not $isdealer)
        {
            $output += "You have $($total).`n"
        }
        else
        {
            $output += "Dealer has $($total).`n"
        }
    }
    else
    {
        #if the dealer's hand is invisible, we don't know their total, so
        #don't display it; also we can only see the second card.
        $output += $cards[1].Card
    }
   
    $output | out-string
}


function Show-Status ($my, $dealer)
{
    Write-Host "Your cards:"
    Write-Host (Print-VisibleCards -cards $my.Cards -allcardsvisible $TRUE) -foregroundColor Green
   
    Write-Host "Dealer's cards:"
    Write-Host (Print-VisibleCards -cards $dealer.Cards -isdealer -allcardsvisible $dealer.AreAllCardsRevealed ) -foregroundColor Red
}


function Show-Action ($text)
{
    Write-Host $text -foregroundColor Yellow
    Start-Sleep -seconds 1
}


function Solve-Problem10
{
    $deck = Create-DeckObject
   
    $myHand = Create-HandObject
    $dealerHand = Create-HandObject -isdealer
   
    Show-Action "Dealing starting hands…"
    $myHand.Cards += $deck.Deal
    $dealerHand.Cards += $deck.Deal
    $myHand.Cards += $deck.Deal
    $dealerHand.Cards += $deck.Deal


    #show starting hands
    Show-Status -my $myHand -dealer $dealerHand
   
   
    #give the player the option to hit
    while ($myHand.BlackjackValue -lt 21)
    {
        Write-Host -noNewLine "Stay (s) or Hit (h) ? "
        if ((Read-Host) -match "h")
        {
            Show-Action "You have chosen to Hit."
            $myHand.Cards += $deck.Deal
            Show-Status -my $myHand -dealer $dealerHand
        }
        else
        {
            Show-Action "You have chosen to Stay."
            break
        }
    }
   
    #did we bust? If so, quit.
    if ($myHand.BlackjackValue -gt 21)
    {
        Show-Action "YOU LOSE! You busted!"
        return
    }


    #dealer reveals their cards
    $dealerHand.AreAllCardsRevealed = $TRUE
    Show-Action "Dealer has revealed their cards."


    Show-Status -my $myHand -dealer $dealerHand
    #extra delay so that we can process what is in the dealer's hand.
    Start-Sleep -seconds 3
   
   
    #give the dealer the option to hit
    while ($dealerHand.BlackjackValue -lt $myHand.BlackjackValue)
    {
        Show-Action "Dealer takes a card."
        $dealerHand.Cards += $deck.Deal
        Show-Status -my $myHand -dealer $dealerHand
    }
   
    #did dealer bust? If so, VICTORY!
    if ($dealerHand.BlackjackValue -gt 21)
    {
        Show-Action "YOU WIN! VICTORY! Dealer busts!"
    }
    else
    {
        Show-Action "YOU LOSE! Dealer has $($dealerHand.BlackjackValue), you have $($myHand.BlackjackValue)."
    }
}


Solve-Problem10

2008 Winter Scripting Game Events: Index

Categories: PowerShell
Technorati:
Wednesday, April 23, 2008 3:47:17 AM UTC  #     |  Comments [0]  |  Trackback
Wednesday, April 23, 2008 3:46:56 AM UTC #

If you aren't already in the know, these ten problems are from the 2008 Winter Scripting games.

For each problem, I'm going to quickly sum up the interesting (interesting TO ME) bits of each problem, then I'm going to post the full source.

Event 9: You're Twisting My Words

Simple: reverse letters in each word, WITHOUT reversing the order of the words. It's a simple case of breaking down the huge string into tokens, then reversing the contents of the tokens, then re-combining the tokens. Actually it's even simpler than I described. Moving on.

Source

#PROBLEM #9
function Reverse-LettersInWord ($word)
{
    $reversedChars = @()
    for ($i = $word.Length - 1; $i -ge 0; $i)
    {
        $reversedChars += $word[$i]
    }
   
    [string]::Join("", $reversedChars)
}


function Solve-Problem9
{
    [string]::Join(" ", ( ( (cat "C:\Scripts\alice.txt").Split(" ") ) | % { Reverse-LettersInWord -word $_ } ) )
}



Solve-Problem9

2008 Winter Scripting Game Events: Index

Categories: PowerShell
Technorati:
Wednesday, April 23, 2008 3:46:56 AM UTC  #     |  Comments [0]  |  Trackback
Wednesday, April 23, 2008 3:46:35 AM UTC #

If you aren't already in the know, these ten problems are from the 2008 Winter Scripting games.

For each problem, I'm going to quickly sum up the interesting (interesting TO ME) bits of each problem, then I'm going to post the full source.

Event 8: Making Beautiful Music

In this problem, we are asked to generate a random playlist for our CDs. I'll just say: I cheated. If you look carefully, you'll notice I sorted the songs from longest to shortest, making the "song packing" algorithm more likely to succeed. But it's not perfect and can fail.

So, in summary, I solved the problem like everyone else, but probably not well enough.

Source

#PROBLEM #8
$filename = "C:\Scripts\songlist.csv"
$global:nextId = 0
$minimumSecondsPerCd = (75 * 60)
$maximumSecondsPerCd = (80 * 60)
$maximumSongsPerArtistOnPlaylist = 2


function Create-SongObject ($artist, $title, $durationString)
{
    $o = new-object PSObject


    Add-Member -inputObject $o -memberType NoteProperty -name "Artist" -value $artist
    Add-Member -inputObject $o -memberType NoteProperty -name "Title" -value $title
    Add-Member -inputObject $o -memberType NoteProperty -name "Duration" -value $durationString


    Add-Member -inputObject $o -memberType ScriptProperty -name "GetSeconds" -value { Get-DurationInSeconds $this.Duration }


    Add-Member -inputObject $o -memberType NoteProperty -name "Id" -value $nextId
    $global:nextId++


    Add-Member -inputObject $o -memberType ScriptProperty -name "PrintDetails" -value { "$($this.Artist)`t$($this.Title)`t$($this.Duration)"}
   
    $o
}


#POSTSCRIPT-OOPS: I forgot the TimeSpan class! Argh! Instead of
#using TimeSpan, I implement it again here below!
function Get-DurationInSeconds ($durationString)
{
    $column = $durationString.Split(":")
    $minutes = [int]$column[0]
    $seconds = [int]$column[1]
   
    $minutes * 60 + $seconds
}


function Get-AvailableSongs
{
    foreach ($line in (cat $filename) )
    {
        $column = $line.Split(",")
        Create-SongObject -artist $column[0] -title $column[1] -durationString $column[2]
    }
}


function Sum-PlaylistTime ($playlist)
{
    #initialize to 0 in case of empty playlist
    $totalSeconds = 0
   
    foreach ($song in $playlist)
    {
        $totalSeconds += $song.GetSeconds
    }
   
    $totalSeconds
}


#POSTSCRIPT-OOPS: ok, well, this isn't an oops moment
#necessarily. But I do apologize for the THIRTY ONE
#CHARACTER variable name used below. 31!
function Has-PlaylistReachedArtistSongLimit ($artist, $playlist)
{
    $playlistArtistSongCount = $playlist | group Artist | ? { $_.Name -eq $artist } | % { $_.Count }
   
    $maximumSongsPerArtistOnPlaylist -le $playlistArtistSongCount
}


function Add-NextEligibleSong ($catalog, $existingPlaylist)
{
    $existingPlaylistIds = $existingPlaylist | % { $_.Id }
   
    foreach ($candidateSong in $catalog)
    {
        if ($existingPlaylistIds -contains $candidateSong.Id)
        {
            continue
        }
       
        if ( Has-PlaylistReachedArtistSongLimit -artist $candidateSong.Artist -playlist $existingPlaylist )
        {
            continue
        }
       
        #I should handle the possibility of building a playlist in a combinatorial manner, i.e.
        #I should be attempting to remove songs to make room for others if necessary.
        #this would be the spot for it (would require some restructuring in how I add/remove songs from the list)
        if ( ((Sum-PlaylistTime $existingPlaylist) + $candidateSong.Seconds) -gt $maximumSecondsPerCd)
        {
            continue
        }


        return $candidateSong
    }
   
    Throw "No candidate songs remain."
}


function Solve-Problem8
{
    $songs = Get-AvailableSongs | sort GetSeconds -desc
   
    $myPlaylist = @()
   
    while ((Sum-PlaylistTime $myPlaylist) -lt $minimumSecondsPerCd )
    {
        $myPlaylist += Add-NextEligibleSong -catalog $songs -existingPlaylist $myPlaylist
    }
   
    foreach ($song in $myPlaylist)
    {
        Write-Host $song.PrintDetails
    }
   
    $totalSeconds = Sum-PlaylistTime $myPlaylist
    $totalMusicMinutes = [int]([Math]::Floor($totalSeconds / 60))
    $totalRemainingSeconds = $totalSeconds % 60
    $totalMusicTime = "$($totalMusicMinutes):$($totalRemainingSeconds)"
   
    Write-Host "`nTotal music time: $totalMusicTime"
}




Solve-Problem8

2008 Winter Scripting Game Events: Index

Categories: PowerShell
Technorati:
Wednesday, April 23, 2008 3:46:35 AM UTC  #     |  Comments [0]  |  Trackback
Wednesday, April 23, 2008 3:46:13 AM UTC #

If you aren't already in the know, these ten problems are from the 2008 Winter Scripting games.

For each problem, I'm going to quickly sum up the interesting (interesting TO ME) bits of each problem, then I'm going to post the full source.

Event 7: Play Ball!

Here we are asked to randomly schedule games for six teams in a round robin tournament. Apparently I used Knuth's classic list order randomization algorithm, which I remember attempting to implement, badly, and failing!,  in high school. Yay for progress.

Otherwise the solution is straightforward: two nested loops, generate matches in a "combinatorial" way, then randomize the order. Boom, done.

Source

#PROBLEM #7
$teams = @("A", "B", "C", "D", "E", "F")


#bad random number generator
$rnd = new-object Random


function Create-GameObject ($game)
{
    $o = new-object PSObject
    Add-Member -inputObject $o -memberType NoteProperty -name "Game" -value $game
   
    Add-Member -inputObject $o -memberType NoteProperty -name "RandomOrder" -value $rnd.NextDouble()   
   
    $o
}


function Generate-RoundRobinGames
{
    for ($firstTeamIndex = 0; $firstTeamIndex -lt $teams.Count; $firstTeamIndex++)
    {
        for ($secondTeamIndex = $firstTeamIndex + 1; $secondTeamIndex -lt $teams