Last minute geek

last minute tech news from around the net

You are here: English WTF

WTF

CodeSOD: Lucee Execution

I Love Lucy title

Recently, at my dayjob, I had a burning need to understand how scheduled tasks work. You see, we've recently switched from Adobe Coldfusion to Lucee, and I was shaky on how Adobe did things before, so I wanted a deeper understanding of how the code I was working on would be executed. For the uninitiated, Lucee is an open-source reimplementation of Cold Fusion. And that's not the WTF.

It's open source, I thought to myself. I'll just take a look at the code.

I had one problem. Then I looked at the code. Now I have two problems ... and a headache:


private long calculateNextExecution(long now, boolean notNow) {
	long nowTime=util.getMilliSecondsInDay(timeZone,now);
	long nowDate=now-nowTime;
		
		
	// when second or date intervall switch to current date
	if(startDate<nowDate && (cIntervall==Calendar.SECOND || cIntervall==Calendar.DATE))
		startDate=nowDate;
		
	// init calendar
	Calendar calendar = JREDateTimeUtil.getThreadCalendar(timeZone);
	calendar.setTimeInMillis(startDate+startTime);
		
	long time;
	while(true) {
		time=getMilliSecondsInDay(calendar);
		if(now<=calendar.getTimeInMillis() && time>=startTime) {
			// this is used because when cames back sometme to early
			if(notNow && (calendar.getTimeInMillis()-now)<1000);
			else if(intervall==ScheduleTaskImpl.INTERVAL_EVEREY && time>endTime)
				now=nowDate+DAY;
			else 
				break;
		}
		calendar.add(cIntervall, amount);
	}
	return calendar.getTimeInMillis();
}

"So okay, if now is before or starting at—hang on, what's calendar again?" I found myself muttering aloud. "Okay, if now is before or equal to the start date plus the start time, and time—which, if I understand that method correctly, is the elapsed time in the current day—is after or equal to the start time ... when is that true exactly? You know what would be nice? Some #%#@$%@ Javadoc!"

This is only one representative method, and yet, there's just so much here. Why an if statement that does nothing, terminating in an easily-overlooked semicolon? Why the misspelling of EVERY? Or "Intervall?" Why are the programmers allergic to spaces? Why can't they name variables worth anything? Do I even really want to know how this works anymore?

If you want to witness the madness for yourself, may I remind you: this code is open source. Have at ye. According to the copyright statement at the top, this code was inherited from the Railo project, so if you're in Switzerland, please be sure to send your hate mail to the right address.

[Advertisement] Manage IT infrastructure as code across all environments with Puppet. Puppet Enterprise now offers more control and insight, with role-based access control, activity logging and all-new Puppet Apps. Start your free trial today!

Read all

Take the Bus

Rachel started working as a web developer for the local bus company. The job made her feel young, since the buses, the IT infrastructure, and most of their back-office code was older than she was. The bus fare-boxes were cash only, and while you could buy a monthly pass, it was just a little cardboard slip that you showed the driver. Their accounting system ran on a mainframe, their garage management software was a 16-bit DOS application. Email ran on an Exchange 5.5 server.

Translink-B8017

In charge of all of the computing systems, from the web to DOS, was Virgil, the IT director. Virgil had been hired back when the accounting mainframe was installed, and had nestled into his IT director position like a tick. The bus company, like many such companies in the US, was ostensibly a private company, but chartered and subsidized by the city. This created a system which had all the worst parts of private-sector and public-sector employment merged together, and Virgil was the master of that system.

Rachel getting hired on was one of his rare “losses”, and he wasn’t shy about telling her so.

“I’ve been doing the web page for years,” Virgil said. “It has a hit counter, so you can see how many hits it actually gets- maybe 1 or 2 a week. But management says we need to have someone dedicated to the website.” He grumbled. “Your salary is coming out of my budget, you know.”

That website was a FrontPage 2000 site, and the hit-counter was broken in any browser that didn’t have ActiveX enabled. Rachel easily proved that there was far more traffic than claimed, not that there was a lot. And why should there be? You couldn’t buy a monthly pass online, so the only feature was the ability to download PDFs of the hand-schedules.

With no support, Rachel did her best to push things forward. She redesigned the site to be responsive. She convinced the guy who maintained their bus routes (in a pile of Excel spreadsheets) to give her regular exports of the data, so she could put the schedules online in a usable fashion. Virgil constantly grumbled about wasting money on a website nobody used, but as she made improvements, more people started using it.

Then it was election season. The incumbent mayor had been complaining about the poor service the bus company was offering, the lack of routes, the costs, the schedules. His answer was, “cut their funding”. Management started talking about belt-tightening, Virgil started dropping hints that Rachel was on the chopping block, and she took the hint and started getting resumes out.

A miracle occurred. The incumbent mayor’s campaign went off the rails. He got caught siphoning money from the city to pay for private trips. A few local cops mentioned that they’d been called in to cover-up the mayor’s frequent DUIs. His re-election campaign’s finances show strange discrepancies, and money had come in that couldn’t be tied back to a legitimate contribution. He tried to get a newly built stadium named after himself, which wasn’t illegal, but was in poor taste and was the final straw. He dropped out of the election, paving the way for “Mayor Fred” to take over.

Mayor Fred was a cool Mayor. He wanted to put in bike lanes. He wanted to be called “Mayor Fred”. He wanted to make it easier for food trucks to operate in the city. And while he shared his predecessor’s complaints about the poor service from the bus company, he had a different solution, which he revealed while taking a tour of the bus company’s offices.

“I’m working right now to secure federal grants, private sector funding, to fund a modernization project,” Mayor Fred said, grinning from behind a lectern. “Did you know we’re paying more to keep our old buses on the road for five years than it would cost to buy new buses?” And thus, Mayor Fred made promises. Promises about new buses, promises about top-flight consultants helping them plan better routes, promises about online functionality.

Promises that made Virgil grumble and whine. Promises that the mayor… actually kept.

New buses started to hit the streets. They had GPS and a radio communication system that gave them up-to-the-second location reporting. Rachel got put in charge of putting that data on the web, with a public API, and tying it to their schedules. A group of consultants swung through to help, and when the dust settled, Rachel’s title was suddenly “senior web developer” and she was in charge of a team of 6 people, integrating new functionality to the website.

Virgil made his opinion on this subject clear to her: “You are eating into my budget!”

“Isn’t your budget way larger?” Rachel asked.

“Yes, but there’s so much more to spend it on! We’re a bus company, we should be focused on getting people moving, not giving them pretty websites with maps that tell them where the buses are! And now there’s that new FlashCard project!”

FlashCard was a big project that didn’t involve Rachel very much. Instead of cash fares and cardboard passes, they were going to get an RFID system. You could fill your card at one of the many kiosks around the city, or even online. “Online” of course, put it in Rachel’s domain, but it was mostly a packaged product. Virgil, of all people, had taken over the install and configuration, Rachel just customized the stylesheet so that it looked vaguely like their main site.

Rachel wasn’t only an employee of the bus company, she was also a customer. She was one of the first in line to get a FlashCard. For a few weeks, it was the height of convenience. The stop she usually needed had a kiosk, she just waved her card at the farebox and paid. And then, one day, when her card was mostly empty and she wasn’t anywhere near a kiosk, she decided to try filling her card online.

Thank you for your purchase. Your transaction will be processed within 72 hours.

That was a puzzle. The kiosks completed the transaction instantly. Why on Earth would a website take 3 days to do the same thing? Rachel became more annoyed when she realized she didn’t have enough on her card to catch the bus, and she needed to trudge a few blocks out of her way to refill the card. That’s when it started raining. And then she missed her bus, and had to wait 30 minutes for the next one. Which is when the rain escalated to a downpour. Which made the next bus 20 minutes late.

Wet, cold, and angry, Rachel resolved to figure out what the heck was going on. When she confronted Virgil about it, he said, “That’s just how it works. I’ve got somebody working full time on keeping that system running, and that’s the best they can do.”

Somebody working full time? “Who? What? Do you need help? I’ve done ecommerce before, I can-”

“Oh no, you’ve already got your little website thing,” Virgil said. “I’m not going to let you try and stage a coup over this.”

With an invitation like that, Rachel decided to figure out what was going on. It wasn’t hard to get into the administration features of the FlashCard website. From there, it was easy to see the status of the ecommerce plugin for processing transactions: “Not installed”. In fact, there was no sign at all that the system could even process transactions at all.

The only hint that Rachel caught was the configuration of the log files. They were getting dumped to /dev/lp1. A printer. Next came a game of hide-and-seek- the server running the FlashCard software wasn’t in their tiny data-center, which meant she had to infer its location based on which routers were between her and it. It took a few days of poking around their offices, but she eventually found it in the basement, in an office.

In that office was one man with coke-bottle glasses, an antique continuous feed printer, a red document shredder, and a FlashCard kiosk running in diagnostic mode. “Um… can I help you?” the man asked.

“Maybe? I’m trying to track down how we’re processing credit card transactions for the FlashCard system?”

The printer coughed to life, spilling out a new line. “Well, you’re just in time then. Here’s the process.” He adjusted his glasses and peered at the output from the printer:

TRANSACTION CONFIRMED: f6ba779d22d5;4012888888881881;$25.00

The man then kicked his rolly-chair over to the kiosk. The first number was the FlashCard the transaction was for, the second was the credit card number, and the third was the amount. He punched those into the kiosk’s keypad, and then hit enter.

“When it gets busy, I get real backed up,” he confessed. “But it’s quiet right now.”

Rachel tracked down Virgil, and demanded to know what he thought he was doing.

“What? It’s not like anybody wants to use a website to buy things,” Virgil said. “And if we bought the ecommerce module, the vendor would have charged us $2,000/mo, on top of an additional transaction fee. This is cheaper, and I barely have enough room in my budget as it is!”

[Advertisement] Otter enables DevOps best practices by providing a visual, dynamic, and intuitive UI that shows, at-a-glance, the configuration state of all your servers. Find out more and download today!

Read all

CodeSOD: Hard Reboot

Every day in IT, each one of us walks the fine line between "brilliant" and "appalling." We come across things that make our jaws drop, and we're not sure whether we're amazed or horrified or both. Here's a PHP sample that Brett P. was lucky—or unlucky—enough to discover:

This comes from circa 2001, back when there were MySQL stability issues on a server. If in response to the end user's request the script couldn't connect to the session database, PHP would shell out to a VB6 .EXE that rebooted the machine. Ta dum! No more connection error!


if (strpos(mysql_error(), "connect to MySQL server on 'localhost' (10061)")) {
    // The MySQL Error: Can't connect to MySQL server on 'localhost' (10061)
    // means that the MySQL database is not running. This is caused by a failed
    // reboot. Since MySQL is not running, it is safe to execute a hard boot.
    echo "Currently rebooting the server. Please try again in two minutes.";
    flush();
    exec("c:Progra~1progshardboot.exe");
}

That comment block full of flimsy assumptions and unwarranted confidence makes my insides knot up with dread. I'm leaning toward "appalling" on this one. Anyone else?

[Advertisement] Manage IT infrastructure as code across all environments with Puppet. Puppet Enterprise now offers more control and insight, with role-based access control, activity logging and all-new Puppet Apps. Start your free trial today!

Read all

Error'd: The Maybe Compiler

"Maybe it it compiled...maybe it didn't. I guess that I have to find out myself from here on out," wrote, Y. Diomidov.

 

Ken W. writes, "Does buying the 4 year warranty mean Amazon will replace any steaks that don't last?"

 

"I *KNEW* that I should have gone for the blue one!" Connor C. wrote.

 

Adam writes, "Today was a bad day to switch from Chrome."

 

"Looks like my HP printer had been eating paper behind my back," wrote Peter D.

 

Jeanne P. writes, "Ironically, we came across this while looking for colleges that offer Computer Science or Software Engineering majors. The pie charts show acceptance rates."

 

[Advertisement] Universal Package Manager – store all your Maven, NuGet, Chocolatey, npm, Bower, TFS, TeamCity, Jenkins packages in one central location. Learn more today!

Read all

The Smell-O-Vision

Ron used to work for a company which built “smell-o-visions”. These were customized systems running small form factor Windows PCs that operated smell pumps and fans using USB relays timed to a video to give a so-called “4D Experience.” Their product was gimmicky, and thus absolutely loved by marketing groups.

One such marketing group, whose client was a branch of the military, worked with them to create a gimmick to help with recruiting. A smell-o-vision was installed on a trailer and towed around the country, used to convince teenagers to join the service by making them smell fresh-squeezed orange juice while watching a seizure-inducing video with guns. The trailer was staffed by grunts, and these guys cycled through so frequently that they received little or no training on the system.

A vintage ad for a smell-o-vision film called 'Scent of Mystery'

“Hey Ron,” Sam, his boss, told him one day. “The recruiter is having a ton of trouble with their system and I need you to go on-site and take a look.”

Going on-site was the only option. The recruiter’s system was not on the Internet so remote diagnosis was impossible. And so he soon found himself cooking in the hot desert sun on a base in the Southwest, looking at a small LCD screen on a 1U pull-out tray accessible through an access panel in the trailer.

“This is what it always does,” said the grunt assigned to work with him. “It always says it’s corrupted and the 4D stuff doesn’t work. Rebooting doesn’t fix it.”

Ron looked at the screen as the outdated Windows XP booted up and watched it flash an error stating “Windows was not properly shut down” before beginning a long filesystem scan and repair and then using System Restore to return to an earlier checkpoint. A checkpoint created before the presentation software was installed…

Ron shook his head and started the Help Desk 101 questions. “Do you shut down the system when you’re packing up?”

“Oh, we just turn the generator off,” the grunt answered. “That shuts everything down.”

Ron mentally facepalmed. “You need to properly shut down the system before killing power or this will happen again.” He went inside the trailer and showed them a power button on the control panel. The button was just wired to the power switch header on the PC’s motherboard and acted exactly like any computer case’s power button. Pressing it briefly tells the operating system to shut itself down. “Just press this button and it will shut itself down in a minute or two.”

“Okay, that’s simple enough,” the grunt said.

Then Ron spent the day re-installing and configuring their system by downloading all the software over his phone’s mobile hotspot to his laptop, then transferring it via USB stick. Eventually he had it back up and running. He made sure to stress how important it was to shut down the system, and on a whim left them a DVD with all the software so he could talk someone through the process over the phone if it happened again.

He returned home. And two weeks later, it happened again. He spent three days on the phone talking to a different grunt and walking him through restoring the system. Again he emphasized the importance of shutting down the system with the power button before killing power, but this grunt explained he did that. Ron was confused, but finished the support call.

Just a few days later, they called again. He talked to yet another grunt, asked them how shutdown was handled, and he explained he pressed the button until it shut down. His boss decided to send Ron on-site again, and he repaired the system. It was much faster this time since he had a DVD with everything he needed on it, only taking most of a morning. When he was done, he tested the power button. It shut down the system properly.

“Show me how you get ready for a presentation,” he asked. “From setup once you’re on-site, to shutdown.”

The pair of grunts assigned to him–two more he’d never worked with before–spent an hour walking through the process. When they got to the end, Ron reminded him to shut down the system.

And the grunt did so. By pressing and holding the power button for about five seconds. Which killed power to the PC without properly shutting down the operating system.

He mentally facepalmed again. “No, you can’t press and hold. Just tap the button. It will eventually shut down.” He was getting fast at restoring the system and spent that afternoon correcting it all. This time he took a System Restore snapshot once everything was in place, and taped a hand-written note on the control panel saying “DO NOT HOLD THIS BUTTON TO TURN OFF THE MACHINE. DO NOT SHUT OFF THE GENERATOR WITHOUT FIRST TURNING THE SYSTEM OFF PROPERLY.”

He returned home. And a couple weeks later, they called again. He was unable to fix it over the phone and was sent on-site yet again. This time the filesystem was too corrupted to repair and he had to set everything up from scratch. Upon querying the new grunts he discovered they ignored the note and were still holding the power button to kill the system.

This continued for a couple more months. The client refused to shut down the system properly and was constantly causing severe filesystem corruption or even killing hard disks. Each time the client called, getting angrier and angrier. “It says there is no OS! I thought you fixed this bug!!” Each time the problems were caused by operator error.

During a meeting with his boss Sam, Ron explained all the issues and how much of his time it was taking, and while brainstorming a solution Ron pitched a new idea. “What if we modify the custom power button? Alter it to only send a pulse, instead of a constant closed signal, so it’s impossible to hold it down?”

“Figure it out and do it,” Sam ordered. “These guys are idiots and won’t do things right. They’re killing us on support time, we have to fix this or fire the client. How hard is it to shut this thing down properly?”

So, being a software engineer, Ron devised a clever solution based on an Arduino that sampled the power button’s state and sent pulses to the motherboard’s power button header. It passed all his testing and he went on-site to install it. And finally the support calls ceased completely. This unit was the only one that received the update since none of their other clients had issues with operator error.

With the issue solved, Ron decided to take some badly-needed vacation to attend a family reunion in North Carolina and tried to stay off the grid. Meanwhile, Sam took a demo unit to an expo in London so visitors could smell what it was like to go skiiing.

During his vacation, Ron received a phone call from Sam in the middle of the night. Being on vacation and trying to stay offline, he ignored it. But the phone rang in quick succession several more times and he finally answered.

“Ron! Sorry to wake you, but our demo unit quit working and I need your help!”

Ron grunted. “It’s one AM here…”

“I know but I need to get this back up before the conference starts this morning!”

“Okay,” he said with a sigh. “What’s it doing?”

Sam proceeded to describe a series of error screens over the phone. It stated that “Windows was not shut down properly,” followed by a long filesystem scan, followed by an error that critical system files were corrupted and Windows could not boot.

Ron facepalmed for real this time.

[Advertisement] Universal Package Manager - ProGet easily integrates with your favorite Continuous Integration and Build Tools, acting as the central hub to all your essential components. Learn more today!

Read all

Bring Your Own Code: Your Private Foursome

Last week, I shared some code that, while imperfect, wasn’t that bad. I then issued a challenge: make it worse. Or better, if you really want. As many comments noted: one case covers only the first iteration of the loop, and one case only covers the last iteration of the loop. You could easily pull those out of the loop, and not need a for-case at all. Others noticed that this pattern looked like odd slices out of an identity matrix.

With that in mind, we got a few numpy, Matlab, or MatrixUtils based solutions generally were the “best” solutions to the problem: generate an identity matrix and take slices out of it. This is reasonable and fine. It makes perfect sense. Let’s see if we can avoid making sense.

I’ll start with Abner Qian’s Ruby solution.

module MagicalArrayGenerator
  def magical_array_generator
    main_array = []
    self.times do |i|
      inner_array = []
      self.times do |j|
        i == j ? inner_array << 1 : inner_array << 0
      end
      main_array << inner_array
    end

    e_1 = []
    n_1 = []
    e_n = []
    n_n = []

    self.times do |i|
      e_1 << [main_array[i].first]
      e_n << [main_array[i].last]
      n_1 << main_array[i][1..-1]
      n_n << main_array[i][0..-2]
    end

    [e_1, n_1, e_n, n_n]
  end
end

class Integer
  include MagicalArrayGenerator
end

e_1, n_1, e_n, n_n = 4.magical_array_generator

At it’s core, this is simply an implementation that generates an identity matrix and slices it up. The actual implementation, however, is a pitch-perfect parody of Ruby development: “There’s no problem that can’t be solved by monkey-patching a method into a built-in type”. That’s what happens here- the include statment injects this method into the build-in Integer data-type, meaning you can call 4.magical_array_generator and get your arrays. Abner also points out that Ruby uses 62-bit integers, just in case you want some 4611686018427387903 by 4611686018427387904 arrays.

Several folks looked at the idea of taking slices, and said, “Gee, I bet you I could do this with pointers in C”. My personal favorite in that category would have to be Ron P’s approach.

#include <stdio.h>

int main( int argc, char **argv)
{
    int *e_1 = 0;
    int *e_n = 0;
    int **n_1 = 0;
    int **n_n = 0;
    int *fugly = 0;
    int i,j;

    if ( argc != 2 ) return 1;

    int n = atoi(argv[1]);

    fugly = calloc( n*(n+1),sizeof(int));

    n_1 = calloc(n,sizeof(int *));
    n_n = calloc(n,sizeof(int *));

    for ( i = 0, j=n; i < n; ++i, j+=n+1 )
    {
        fugly[j]=1;
        n_1[i]=fugly+n*i;
        n_n[i]=n_1[i]+n;
    }
    e_1 = fugly+n;
    e_n = fugly+1;

    printf( "e_1n" );
    for ( i = 0; i < n; ++i ) {
      printf( "  %dn", e_1[i]);
    }

    printf( "ne_nn" );
    for ( i = 0; i < n; ++i ) {
      printf( "  %dn", e_n[i]);
    }

    printf( "nn_1n" );
    for ( i = 0; i < n; ++i ) {
      printf( "  " );
      for ( j = 0; j < n-1; ++j ) {
        printf("%d ", n_1[i][j]);
      }
      printf("n" );
    }

    printf( "nn_nn" );
    for ( i = 0; i < n; ++i ) {
      printf( "  " );
      for ( j = 0; j < n-1; ++j ) {
        printf("%d ", n_n[i][j]);
      }
      printf("n" );
    }

    return 0;
}

Now, Martin Scolding gets bonus points for two reasons: first, he uses one of the worst languages in the world (not designed as an esolang), and second, this language doesn’t technically support multi-dimensional arrays. I speak, of course, of PL/SQL. Note the use of substrings to figure out what number to put in each position of the array.

DECLARE

    TYPE data_t  IS TABLE OF INTEGER INDEX BY PLS_INTEGER;
    TYPE array_t IS TABLE OF data_t  INDEX BY PLS_INTEGER;

   e_1 array_t;
   e_n array_t;
   n_1 array_t;
   n_n array_t;

   l_array_size INTEGER := 0;

PROCEDURE gen_arrays(n INTEGER, p_e_1 IN OUT array_t, p_e_n IN OUT array_t, p_n_1 IN OUT array_t, p_n_n IN OUT array_t)
--' Generate 4 Arrays of the form (example n=4)
--
--    '       | 1 |         | 0 0 0 |
--    ' e_1 = | 0 |   n_1 = | 1 0 0 |
--    '       | 0 |         | 0 1 0 |
--    '       | 0 |         | 0 0 1 |
--    '
--    '       | 0 |         | 1 0 0 |
--    ' e_n = | 0 |   n_n = | 0 1 0 |
--    '       | 0 |         | 0 0 1 |
--    '       | 1 |         | 0 0 0 |
--
IS
    l_n_string LONG := RPAD('1',n+1,'0');
BEGIN

    For i in 1..n Loop
        p_e_1(i)(1)   := TO_NUMBER(SUBSTR(l_n_string, 1, 1));
        p_e_n(i)(1)   := TO_NUMBER(SUBSTR(l_n_string, n, 1));
        For j in 1..n-1 Loop
            p_n_1(i)(j) := TO_NUMBER(SUBSTR(l_n_string, j+1, 1));
            p_n_n(i)(j) := TO_NUMBER(SUBSTR(l_n_string, j,   1));
        End Loop;
        l_n_string := LPAD(SUBSTR(l_n_string, 1, n), n+1, '0');
    End Loop;

END;

BEGIN
    l_array_size := &inp_array;

    gen_arrays(l_array_size, e_1, e_n, n_1, n_n);

    --==========================================================================
    -- DISPLAY RESULTS
    --==========================================================================
     DBMS_OUTPUT.PUT_LINE('e_1 = ');
     For i in 1..l_array_size Loop
        DBMS_OUTPUT.PUT_LINE('         | ' || e_1(i)(1) || ' |');
     End Loop;
     DBMS_OUTPUT.PUT_LINE('--------------------------------------------------');
     DBMS_OUTPUT.PUT_LINE('e_n = ');
     For i in 1..l_array_size Loop
        DBMS_OUTPUT.PUT_LINE('         | ' || e_n(i)(1) || ' |');
     End Loop;
     DBMS_OUTPUT.PUT_LINE('--------------------------------------------------');
     DBMS_OUTPUT.PUT_LINE('n_1 = ');
     For i in 1..l_array_size Loop
        DBMS_OUTPUT.PUT('         | ');
        For j in 1..l_array_size-1 Loop
            DBMS_OUTPUT.PUT(n_1(i)(j) || ' ');
        End Loop;
        DBMS_OUTPUT.PUT('|');
        DBMS_OUTPUT.NEW_LINE;
     End Loop;
     DBMS_OUTPUT.PUT_LINE('--------------------------------------------------');
     DBMS_OUTPUT.PUT_LINE('n_n = ');
     For i in 1..l_array_size Loop
        DBMS_OUTPUT.PUT('         | ');
        For j in 1..l_array_size-1 Loop
            DBMS_OUTPUT.PUT(n_n(i)(j) || ' ');
        End Loop;
        DBMS_OUTPUT.PUT('|');
        DBMS_OUTPUT.NEW_LINE;
     End Loop;
     DBMS_OUTPUT.PUT_LINE('--------------------------------------------------');
    --==========================================================================
    --
    --==========================================================================

END;
/

Finally, though, I have to give a little space to Airdrik. While the code may contain some errors, it is in Visual Basic, as was the original solution, and it knows that recursion makes everything better.

Public Sub GenerateIdentitySquare(ByVal n As Long, ByRef sq As Variant, ByVal i As Long, ByVal j As Long)
        Select Case j
        Case i:
                sq(i, j) = #1
                If i < n Then
                        GenerateIdentitySquare(n, sq, i, j+1)
                End If
        Case n:
                sq(i, j) = #0
                GenerateIdentitySquare(n, sq, i+1, 1)
        Case Else:
                sq(i, j) = #0
                GenerateIdentitySquare(n, sq, i, j+1)
        End Select
End Sub

Public Sub CopyRowValues(ByVal n As Long, ByRef sq As Variant, ByRef e As Variant, ByVal sq_i As Long, ByVal e_i As Long, ByVal j As Long)
        e(e_i, j) = sq(sq_i, j)
        if j < n Then
                CopyRowValues(n, sq, e, sq_i, e_i, j+1)
        End If
End Sub

Public Sub CopyRows(ByVal n As Long, ByRef sq As Variant, ByRef e_1 As Variant, ByRef e_n As Variant, ByRef n_1 As Variant, ByRef n_n As Variant, ByVal i As Long)
        Select Case i
        Case 1:
                CopyRowValues(n, sq, e_1, i, 1, 1)
                CopyRowValues(n, sq, n_n, i, i, 1)
                CopyRows(n, sq, e_1, e_n, n_1, n_n, i+1)
        Case n:
                CopyRowValues(n, sq, n_1, i, i-1, 1)
                CopyRowValues(n, sq, n_n, i, i, 1)
        Case Else:
                CopyRowValues(n, sq, n_1, i, i-1, 1)
                CopyRowValues(n, sq, e_n, i, 1, 1)
                CopyRows(n, sq, e_1, e_n, n_1, n_n, i+1)
        End Select
End Sub

Public Sub DefineProjectionArrays(ByVal n As Long, ByRef e_1 As Variant, ByRef e_n As Variant, ByRef n_1 As Variant, ByRef n_n As Variant)
    Dim i As Long, j As Long

    ' Generate 4 Arrays of the form (example n=4)
    '       | 1 |         | 0 0 0 |
    ' e_1 = | 0 |   n_1 = | 1 0 0 |
    '       | 0 |         | 0 1 0 |
    '       | 0 |         | 0 0 1 |
    '
    '       | 0 |         | 1 0 0 |
    ' e_n = | 0 |   n_n = | 0 1 0 |
    '       | 0 |         | 0 0 1 |
    '       | 1 |         | 0 0 0 |

        Dim sq(n, n) As Variant
        GenerateIdentitySquare(n, sq, 1, 1)

    ReDim e_1(n, 1)
    ReDim e_n(n, 1)
    ReDim n_1(n, n - 1)
    ReDim n_n(n, n - 1)

        CopyRows(n, sq, e_1, e_n, n_1, n_n, 1)
End Sub

Functional programming is always the best approach, obviously.

[Advertisement] Release! is a light card game about software and the people who make it. Play with 2-5 people, or up to 10 with two copies - only $9.95 shipped!

Read all

The New Manager

Error Message Example vbs

She'd resisted the call for years. As a senior developer, Makoto knew how the story ended: one day, she'd be drafted into the ranks of the manager, forswearing her true love webdev. She knew she'd eventually succumb, but she'd expected to hold out for a few years before she had to decide if she were willing to change jobs to avoid management.

But when her boss was sacked unexpectedly, mere weeks after the most senior dev quit, she looked around and realized she was holding the short straw. She was the most senior. Even if she didn't put in for the job, she'd be drafted into acting as manager while they filled the position.

This is the story of her first day on the job.

Makoto spent the weekend pulling together a document for their external contractors, who'd been plaguing the old boss with questions night and day— in Spanish, no less. Makoto made sure to document as clearly as she could, but the docs had to be in English; she'd taken Japanese in high school for an easy A. She sent it over first thing Monday morning, hoping to have bought herself a couple of days to wrap up her own projects before the deluge began in earnest.

It seemed at first to be working, but perhaps it just took time for them to translate the change announcement for the team. Just before noon, she received an instant message.

Well, I can just point them to the right page and go to lunch anyway, she thought, bracing herself.

Emilio: I am having error in application.
Makoto: What error are you having?

A minute passed, then another. She was tempted to go to lunch, but the message client kept taunting her, assuring her that Emilio was typing. Surely his question was just long and complicated. She should give him the benefit of the doubt, right?

Emilio: error i am having is: File path is too long

Makoto winced. Oh, that bug ... She'd been trying to get rid of the dependencies with the long path names for ages, but for the moment, you had to install at the root of C in order to avoid hitting the Windows character limits.

But I documented that. In bold. In three places!

Makoto: Did you clone the repository to a folder in the root of a drive? As noted in the documentation there are paths contained within that will exceed the windows maximum path length otherwise
Emilio: No i cloned it to C:Program FilesIntelligent Communications IncClientsAnonymized Company NamePadding for length

Makoto's head hit the desk. She didn't even look up as her fingers flew across the keys. I'll bet he didn't turn on nuget package restore, she thought, or configure IIS correctly.

Makoto: please clone the repository as indicated in the provided documentation, Additionally take careful note of the documented steps required to build the Visual Studio Solution for the first time, as the solution will not build successfully otherwise
Emilio: Yes.

Whatever that means. Makoto sighed. Whatever, I'm out, lunchtime.

Two hours later she was back at her desk, belly full, working away happily at her next feature, when the message bar blinked again.

Dammit!

Emilio: I am having error building application.
Makoto: Have you followed the documentation provided to you? Have you made sure to follow the "first time build" section?
Emilio: yes.
Makoto: And has that resolved your issue?
Emilio: Yes. I am having error building application
Makoto: And what error are you having?
Emilio: Yes. I am having error building application.

"Oh piss off," she said aloud, safe in the knowledge that he was located thousands of miles from her office and thus could not hear her.

"That bad?" asked her next-door neighbor, Mike, with a sympathetic smile.

"He'll figure it out, or he won't," she replied grimly. "I can't hold his hand through every little step. When he figures out his question, I'll be happy to answer him."

And, a few minutes later, it seemed he did figure it out:

Emilio: I am having error with namespaces relating to the nuget package. I have not yet performed nuget package restore

The sound of repeated thumps sent Mike scurrying back across the little hallway into Makoto's cube. He took one look at her screen, winced, and went to inform the rest of the team that they'd be taking Makoto out for a beer later to "celebrate her first day as acting manager." That cheered her enough to answer, at least.

Makoto: Please perform the steps indicated in the documentation for first time builds of the solution in order to resolve your error building the application.
Emilio: i will attempt this fix.

Ten minutes passed: just long enough for her to get back to work, but not so long she'd gotten back into flow before her IM lit up again.

Emilio: I am no longer having error build application.

"Halle-frickin-lujah", she muttered, closing the chat window and promptly resolving to forget all about Emilio ... for now.

[Advertisement] Application Release Automation for DevOps – integrating with best of breed development tools. Free for teams with up to 5 users. Download and learn more today!

Read all