As you've surely guessed, I am not affiliated with the makers of Buffy the Vampire Slayer and/or Fox, who own all rights to all BtVS-related material forever and ever and haven't authorized this site in the slightest bit. Dialogue displayed on this site is NOT intended as copy-right infringement. It IS intended as encouragement of obsessive fan-dom (which really should be in the best interest of the actual copyright owners ;-) ). Please see my FAQ & policies page for the answers to any questions not answered on this page...
(Feb 2002) This site was born back in February 2001, when I finally gave in to the lure of the 25 megs of space that came with my internet access account. 25 megs not being enough for a quality multi-media bonanza, I've opted to keep this site text-oriented -- though now that I've completed my year 1 goal of getting all the episodes in here, my new year 2 goal is to get an episode collage in for each, and if by some miracle I manage that, to start working on arc and/or character collages.
And if you're still reading by this point, I can't help but feel that you're inordinately immune to the soporific powers of reading rambling text, so this is probably an excellent opportunity for me to tell the tale of the "Buffy Database Origin", which though it *does* contain a traumatic event, does *not* involve radioactivity, surrogate animal parents, exploding home worlds, or anything of the sort. (I do however have a tendancy to go off on long, possibly confusing tangents, like this one, within parenthesis, with many commas and such to make you forget about what I was saying before the tangent started. Consider yourself warned!)
The traumatic event in question happened late in October 2000, when my VCR inexplicably opted not to tape the end of "No Place Like Home". I had just moved to Charlottesville, Virginia, which is pretty much the middle of nowhere as far as I'm concerned (my definition of the middle of nowhere being anyplace where you can see cows by simply getting in your car and driving for a few minutes, or where you can't get a single TV channel even marginally watchable with just an antenna. So now you know I've spent my life up until now in the endless suburbia surrounding major metropolitan areas!) and there was no WB affiliate on the cable line-up. However, the neighboring town's NBC affiliate rebroadcast WB programming starting around 1 am, about a week after the WB airdate. (And on a side rant, last summer, my cable company switched, so now I don't get *any* Buffy at all, except from friends via the mail.) So there I was, Sunday morning, happily watching Buffy when all of the sudden the tape cut out. Oh cruel fate! I didn't even get to see the "out for a walk bitch" scene. Argh, and triple argh.
Up until that point, I didn't even know that episodes *had* titles, much less what they were, but I was determined to find out what had happened in the rest of my prematurely aborted episode asap, so I jumped on-line. And rather quickly stumbled into heaven on Psyche's site. Transcripts? Someone types up a transcript of every episode? That is *so* cool! So of course I was downloading like crazy, and converting to palm pilot files so that I could read sprawled out on the couch instead of off the computer screen. It was bliss!
And then I started downloading the wav files. I've moved around a lot since Buffy started airing (Buffy's sophomore year in highschool was my junior year in college and I've never been able to justify lugging that many video tapes around from new dwelling to new dwelling, so there were many episodes I'd only seen once when they first were broadcast. Listening to the wav files of long-forgotten dialogue was like walking down memory lane, way cool. Hello? the web site, when are you going to get to the site already? Patience, I'm almost there!
So having bought a CD burner a while previously which I really hadn't done much with at that point, I decided I wanted to make an audio CD with the wavs I'd downloaded. And I wanted to put them in order by character, and have them kinda flow and have a good rhythm. But I couldn't keep that much dialogue in my head to figure out the best order. Now do you see where I'm going with this? So I made a database, with a record for each wav file and a memo field to hold the text, copy-pasted from Psyche's site, and an "order" field so that I could audition potential clip sequences and that was the first Dialogue Database. At that point I realized that just *reading* the clips in order was very nearly as cool as listening to them, and ideas on that front started to brew.
At the same time, my initial hunt for Buffy info had gotten me started browsing BtVS web sites, reading reviews, looking at fanart etc, and by the time January rolled around, I was starting to think that given that I do after all work as a web programmer, I really should join the fray. My internet access came with web-space I hadn't been using at all, so I started e-mailing tech-support to get it set up for me. I figured if I was going to this, I wanted to try to contribute something new & unique, so I decided to build on my original database and make a site centered around dialogue quotes, using the framework of a database to allow many different ways of viewing, organizing & searching the same material. Being an ex-lit major, the idea of being able to follow threads & themes across multiple episodes was particularly interesting to me, and the story arc lists were really what I considered (and still do) the heart of the site.
The original site was even plainer than it is now, if you can believe it, a solid black background with just the "Buffy DB" logo at the top and that was the only image in the whole site. It was actually a little game I played with myself, I wanted to see how cool looking I could make a site without using any graphics at all. It had a certain austere charm, and it certainly was high up there on the useability scale though of course it wasn't horribly exciting. Then in late spring and early summer I decided I'd proved my point (to myself anyway!) and should now proceed with spiffing things up, and so I started adding the character images, the background, the new home page layout, and other features like the AKAs, Quips & puns, etc. I'm considering another revamp in the near future, but it's not broke, so I'm not sure if there's a point to fixing it. But we'll see, maybe I'll be inspired. For nostalgia's sake, here's the original text from the home page:Welcome to the Buffy Dialogue Database. This is a little project of mine (O.K., big project, but we're going to pretend it's NOT scary how much time I've devoted to it) designed to facilitate some fun trips through the Buffyverse via various significant and/or just plain amusing snatches of dialogue. Click on the links above to start exploring.
Obviously this is still a work in progress. I'll be adding new episodes as they become available to me, and working backwards through old episodes as time allows. I start with a transcript of the episode, and extract snippets of interesting dialogue to add to my database. Each one is given a title, and marked as to what episode it was in, what order it appeared in, who was speaking, and what overall story arc (if any) it played a role in. With that done, automatic scripting adds the clip to all appropriate pages. So the same clip will figure on the character pages of each named speaker, on any relevant Story Arc pages, and on the appropriate Episode page. Not only should this make it easy to browse through the clips in whatever way you prefer, it should also be interesting from a literary perspective to see what kind of patterns emerge from bringing clips from far-flung episodes and scenes together.
The "character" pages are done automatically by a script that goes through each clip looking for the character's name. For that reason, these may not be perfect (for example, "Faith" shows up in clips where people are talking about having faith in something as well as ones where Faith is actually being referred to, so her page has some extraneous clips listed. Ditto for "Glory".). The "Story Arcs" are extremely arbitrary. I've added those manually, and assigned clips to them based on my own analysis (or misanalysis, or mistake, as the case may be!). The episode lists should display the clips in order. I've tried to include all the significant and/or funny bits in a given episode, but it's quite possible that I've missed some in my efforts to skim the cream.
So that is the long, winding story about how a misbehaving VCR caused this site to come into being. I can't believe you read this far, you're a real trooper! Oh, and btw, my little birthday graphic uses the "let it burn" quote from "Innocence" and a picture I took with my digital camera of a birthday candle I happened to have, stuck in a marshmellow, because that's the only thing I could find to hold it upright with! Click here for a close-up. The vcr graphic is my actual vcr, again using my digital camera to capture the image and Photoshop to make it look a lot cooler than it really is. Ditto the CD.
And for those of you who are still awake and curious about the technical side of things, this site is actually a static export of a dynamic site I have running locally. Basically I have an Access DB to store all the clips, episode & arc info, and an ODBC connection for it so that I can access it via MS Personal Server. I also have a single-license version of Cold Fusion Server running locally (similar to ASP or PHP). I do web design/CF programming for a living, so it was easy for me to create editing forms I can use via my browser, and other pages to display the output. But since no one else can see my personal server, I wrote a script that will capture the dynamic content of my database-dependant pages and store them as static html files. Then I can upload those html files to any web account, without having to worry about db connectivity, Cold Fusion support, server load, etc. So far it's working out really nicely, and I highly recommend it as a low-cost alternative to having a live dynamic site. Especially since I think we all know by now that a database-based site is THE only way to go for anything more than a few pages... Trust me, even I have enough of a life to balk at hand-coding the 4-5 thousand pages in this site. There are actually around 20 real pages, of which the pages you see are just versions w/ different data coming out of the database.
Nov 27, 2002 (from my LJ)So the other day things were slow, I was bored, and I thought to myself: hey, you know that conversion of the BuffyDB to PHP you've been thinking about in that vague way that tends to indicate it's not really going to happen? Why not start now? And I thought to myself: self... that's a good idea! I had no real plans to make any solid progress, just a little dabble here and there to get the ball rolling. That ball was a slick one though, it got rather a lot further than I would have expected. This PHP thing's not so tough!
First a little background. As the system currently exists, I have a local database (Access) and a set of editing scripts written in Cold Fusion, also running locally. I have another set of scripts that dives into the DB, grabs the data, and formats it into static HTML pages, which are then transferred by FTP to the server. This gives me some of the primary the advantages of a DB-based site without the need to fork over for CF hosting, which was the only server-side scripting language I knew at the time.
I still think this is a solid way to go for a small site, cheap, reliable, easy. Unfortunately, BuffyDB is by no stretch of the imagination a small site. There are something in the neighborhood of 4,000 pages. Transferring new versions of all those static files takes around 45 minutes via ftp. I managed to cut down on that by modifying my uploading script so that it only uploads new versions of pages that it thinks have changed, but that's always a little iffy 'cause the algorithm for selecting "modified" pages is very complex (for example, let's say I edit a clip record. That means that the arc page for any arc that that clips was part of might potentially change, as well as the episode page, and any other page that references that clip. And that's a simple example). So once a month, I do a full sweep and upload new versions of *all* the pages, and that takes forever and a year. But the kicker is the load count/votes. I like to keep track of those, but a generic log analyser's not going to cut it. So I learned a smattering of cgi and was able to write a couple of little scripts that keep counters going, stored in one text file for each clip. Every month, these are all reset. But all these little text files have to be downloaded and then parsed out so that they can be inserted into the database. Every.Time.I.Want.Current.Stats. Takes a *long* time. And have you ever had a zillion tiny text files in one directory? Windows really doesn't like that.
All this to say, a change is needed, I've outgrown the old system. Enter PHP. My Knight in Shiny Armor.
My new PHP-enabled web-space comes with MySQL rather than access, so I can't just ftp my local db up to the server and live happily ever after. I don't use a gui interface to the db, preferring to do all my manipulations via SQL statements (surpise, no?), so importing the data required some trickiness. The simplest thing to do (and it's not that simple!) is to write yet another local script that outputs the entire contents of the Access database to a text file. The trick is to format the data into new sql statements which I can run on the server to insert the data into the MySQL database. Got that? Don't worry, I'll come back to it. But what do I do when I need to make changes? I'd have to build a new set of editing pages in PHP on the server. And during the month or so that I anticipate running both the current version and a beta of the PHP, I'd have to make the changes to *both* databases. NUH-and-let-me-emphatically-add-UH. And what about back-ups? I don't have server access to the mysql database, so back-ups means writing a php script to output the database contents into some format that I could in theory import into a new database. Which is how I do it with Tangled Synthesis. But given how much work has gone into gathering the data for the BuffyDB, I really don't like the idea of my primary copy of the database living off in cyberspace.
So I'm taking this idea one step further. Instead of writing a one shot export/import script, I've written a sync script. Sync script will check the local database for changes. Any records that have been modified or added since the last update will be exported to an update file in the format of a SQL statement that updates all the fields in that record, with accompanying PHP to run that SQL statement. This update file is ftped to the server, where I then run it by loading the URL to it. The PHP is executed, the SQL statements are run against the MySQL database, and the records in the MySQL database are thus updated to match the contents of the local Access database. Once I confirm that all the statements have run successfully, I reset the flags on the local database by clicking on a link, and go about my business until the next batch of changes. Pretty slick, if I do say so myself.
The coolest part is that I've actually writing in 3 nested languages. I used Cold Fusion scripting to output text which happens to be PHP scripting. And within the PHP scripting are bits of SQL scripting to manipulate the database. I'll freak you out by demonstrating:
<CFOUTPUT query=getrecords> $s="SELECT * from #attributes.phptablename# where ID=#caller.ID#"; print "CHECK QUERY: " . $s; $result=mysql_query($s); print mysql_error(); if (mysql_num_rows($result)==0) { // insert $s="INSERT INTO #attributes.phptablename# (ID,#attributes.numeric# <CFIF len(attributes.numeric) and len(attributes.nonnumeric)>,</cfif>#attributes.nonnumeric#) VALUES (#caller.id#,<CFLOOP list="#attributes.numeric#" index="c"> <CFSEt x=evaluate("caller.#c#")><CFIF len(x)>#x#<CFELSE>NULL</cfif> <CFIF not c is listlast(attributes.numeric)>,</cfif></cfloop> <CFIF len(attributes.numeric) and len(attributes.nonnumeric)>,</cfif> <CFLOOP list="#attributes.nonnumeric#" index="c"> <CFSEt x=evaluate("caller.#c#")><CFSEt x=replace(x,"'","''","all")> <CFSEt x=replace(x,"""","\""","all")><CFIF len(x)>'#x#'<CFELSE>NULL</cfif> <CFIF not c is listlast(attributes.nonnumeric)>,</cfif></cfloop>)"; } else { //update <CFINCLUDE template="phpupdate.cfm"> }; </cfoutput>The parts in tags that start with "CF" are Cold Fusion tags, and the variables surrounded with #s are Cold Fusion variables. When run, the cf if statements will be evaluated, and the variables will be replaced, and this bit of script will thus output valid PHP, including one statement where the variable s ("$" denotes variables in PHP) is set to a text string that just happens to be a sql statement.
So how's this better than the old export-to-static method? Well for one thing, the "what has changed since last time" algorithms is super easy. I just have a field in each table called "synccode". Synccode is 1 by default. I've modified every editing script so that whenever a record is updated, syncode is set to 0. The sync script just looks for records with synccodes of 0. After a successful sync, the code is reset to 1. And because all the pages draw from the record, all I have to do is update the database, not figure out what pages might make reference to that particular record, like I do with the old version. Also, with the export-to-static method, the same data is outputted in static form on all sorts of pages, which is inefficient from a file-storage perspective. For example, each clip is on its own page and most are on an arc page too. That means that space-wise, I'm taking up twice as much room with a static version for each clip as I would just having one copy in the database. And uploads of the update script are much quicker than updates of the static html, because there's just the raw data, not all the formatting, to worry about. (that'll add to the dramatic decrease in space needed to store the site, since the formatting will also be added on the fly, from a single copy of the code) *AND* I won't have to write my stat counters to text file, I can just use a table in the database.
So, yesterday I finished up scripts for formatting the PHP/SQL statements to update each of the 11 tables, and all my data is now ported over to the MySQL database. I have to work on the stats/votes scripting, but most of the rest is going to be pulling the from the database and formatting, which shouldn't be too bad, especially since I already know what I want, I just need to translate my existing CF to PHP. And then, the extra fun part, take advantage of the new tools at my disposal now that I can actually do live scripting. First on my list is to write my own search engine. That will be able to group results by episode, and give you various advanced search options, including requiring that certain speakers are in the quote, and anything else I can dream up. Suggestions welcome!
How long is this going to take me? No idea. I feel like with the data snyc in (apparently) happy working order, the worst is over, which may make me lazy and slow about getting to the rest. I would however like to have a beta version released in time for a solid 2-3 weeks of use before I add the next new ep of the new year (so a week after it debuts) so that I can catch any glitchiness. On a side note, the php hosting has not been as reliable as the cstone hosting, so I will probably leave the last static version up indefinitely as a back-up, just like I did with the tripod version of TS. Also to catch all those links pointed to various clips and arcs that are currently floating out in cyberspace.
And there my friends is my own personal brand of Too Much Information ;-)
Comments, suggestions for new features, questions, corrections, inspired ramblings, etc are always welcome via the contact form.
Oh, and btw, if you're looking to start a site of your own, you may be interested to know that this site is hosted by Powweb. Get 1000 MBS of space, 150 G monthly transfer, lots of e-mail, PHP/MySQL, 30 day trail, etc for $7.77/mo. Add domain registration costs, that's still only around $9/mo. And if you sign up through this link, I get a credit to my account, so if you feel like supporting this site, please consider powweb ;-) [/END SHAMELESS PLUGGING] ALso, if you're interested in learning more about PHP/MySQL sites like this one, learn how to build your own at WebMonkey.
Banners & Buttons
If you collect links, I've created the following banners/buttons for your posting pleasure:
Please right click to download, and then re-post on your server rather than linking to mine. The following code (adjusted to reflect where you saved the file) should display the banner/button for you:
<A HREF="http://vrya.net/bdb" target="_blank"><IMG src="[your image directory here]/[filename].jpg" alt="The Buffy DB -- A searchable database of BtVS dialogue and more..." border=0></A>
Here's Luck has generously provided this additional button for your use if the ones above are too big for you:
<A HREF="http://vrya.net/bdb" target="_blank"><IMG src="[your image directory here]/dbbuttonv2.jpg" width=100 height=35 alt="The Buffy DB -- A searchable database of BtVS dialogue and more..." border=0></A>
Awards & Honors.
And while I'm at it, here are some awards I've won. Aww, shucks, thanks guys!
I'm also fortunate enough to have my essay archived on slayage.tv and my site listed in Nikki Stafford's new book "Bite Me!" (page 146, but the URL is wrong).
Official Legal Verbage:
1. Legal Notice
"Buffy The Vampire Slayer" and "Angel" TM and © (or copyright) Fox and its related entities. All rights reserved. Any reproduction, duplication or distribution of these materials in any form is expressly prohibited.
2. Disclaimer
This web site, its operators and any content on this site relating to "Buffy The Vampire Slayer" and "Angel" are not authorized by Fox. No copyright infringement is intended.