CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
Nested While Loops, foreach and next

 



_Chipwiz_Ben_
Novice

Jun 1, 2011, 9:11 AM

Post #1 of 9 (1961 views)
Nested While Loops, foreach and next Can't Post

I'm trying to build a script that checks link availability and licence costs for given frequencies, channel widths and antenna lengths. Some antenna lengths are not compatible with certain frequencies. The purpose of this section of code is to compare all frequency, channel width and antenna length combination and calculate the availability but not running the subroutines for availability and price calculations if the frequency does not match the antenna length.


Code
$FREQUENCY_QUERY = $dbh->prepare("SELECT `id`, `frequencies` 
FROM `microwave-frequencies`
ORDER BY `frequencies` DESC");

$CHANNEL_QUERY = $dbh->prepare("SELECT `channel`
FROM `microwave-modulation-lookup`
WHERE `rate` = '$DATA_RATE'");

$SITE_A_ANTENNA_LENGTH_QUERY = $dbh->prepare("SELECT `length`
FROM `microwave-antenna-length-lookup`");

$SITE_B_ANTENNA_LENGTH_QUERY = $dbh->prepare("SELECT `length`
FROM `microwave-antenna-length-lookup`");

$FREQUENCY_QUERY->execute( );
while ( ($FREQUENCY_ID) = @FREQUENCY_QUERY = $FREQUENCY_QUERY->fetchrow_array() )
{

$FREQUENCY_ID = "$FREQUENCY_QUERY[0]";
$FREQUENCY = "$FREQUENCY_QUERY[1]";


$CHANNEL_QUERY->execute( );
while ( ($CHANNEL_SIZE) = @CHANNEL_QUERY = $CHANNEL_QUERY->fetchrow_array() )
{

$CHANNEL_SIZE = "$CHANNEL_QUERY[0]";


$SITE_A_ANTENNA_LENGTH_QUERY->execute( );
foreach ( ($SITE_A_ANTENNA_LENGTH) = @SITE_A_ANTENNA_LENGTH_QUERY = $SITE_A_ANTENNA_LENGTH_QUERY->fetchrow_array() )
{

$SITE_A_ANTENNA_LENGTH = "$SITE_A_ANTENNA_LENGTH_QUERY[0]";


$SITE_B_ANTENNA_LENGTH_QUERY->execute( );
foreach ( ($SITE_B_ANTENNA_LENGTH) = @SITE_B_ANTENNA_LENGTH_QUERY = $SITE_B_ANTENNA_LENGTH_QUERY->fetchrow_array() )
{

$SITE_B_ANTENNA_LENGTH = "$SITE_B_ANTENNA_LENGTH_QUERY[0]";

&conflict_check;
&calculate_rsl;
&calculate_oav_h;
&calculate_oav_v;
&calculate_licence_fee;

$tb->addRow( "$TABLE_ROW_COUNT", "$DATA_RATE Mbps", "$FREQUENCY GHz", "$CHANNEL_SIZE MHz", "$SITE_A_ANTENNA_LENGTH", "$SITE_B_ANTENNA_LENGTH", "$OVERALL_AVAILABILITY_H_RESULT %", "$OVERALL_AVAILABILITY_V_RESULT %", "&pound;$ANNUAL_LICENCE_FEE", "<a href='ofcom-document-generator.cgi?LINKDETAILS=True&FREQUENCY=$FREQUENCY&CHANNEL_SIZE=$CHANNEL_SIZE&SITE_A_ANTENNA_LENGTH=$SITE_A_ANTENNA_LENGTH&SITE_B_ANTENNA_LENGTH=$SITE_B_ANTENNA_LENGTH'>Link Details</a>" );
$TABLE_ROW_COUNT++;

if ($LINK_TYPE eq 'Core Infrastructure') {
if ($OVERALL_AVAILABILITY_H_RESULT >= 99.99) {
$tb->setCellClass ($TABLE_ROW_COUNT, 7, 'tbrowgreen');
}
elsif ($OVERALL_AVAILABILITY_H_RESULT < 99.99) {
$tb->setCellClass ($TABLE_ROW_COUNT, 7, 'tbrowerror');
}

if ($OVERALL_AVAILABILITY_V_RESULT >= 99.99) {
$tb->setCellClass ($TABLE_ROW_COUNT, 8, 'tbrowgreen');
}
elsif ($OVERALL_AVAILABILITY_V_RESULT < 99.99) {
$tb->setCellClass ($TABLE_ROW_COUNT, 8, 'tbrowerror');
}
}
elsif ($LINK_TYPE eq 'Customer Link') {
if ($OVERALL_AVAILABILITY_H_RESULT >= 99.95) {
$tb->setCellClass ($TABLE_ROW_COUNT, 7, 'tbrowgreen');
}
elsif ($OVERALL_AVAILABILITY_H_RESULT < 99.95) {
$tb->setCellClass ($TABLE_ROW_COUNT, 7, 'tbrowerror');
}

if ($OVERALL_AVAILABILITY_V_RESULT >= 99.95) {
$tb->setCellClass ($TABLE_ROW_COUNT, 8, 'tbrowgreen');
}
elsif ($OVERALL_AVAILABILITY_V_RESULT < 99.95) {
$tb->setCellClass ($TABLE_ROW_COUNT, 8, 'tbrowerror');
}
}
}
}
}
}


For some reason, the two inner most foreach's, if I change them to whiles, seem to ignore the &conflict_check; next statement and throw up a logarithmic error due to the fact that the frequency does not work with the antenna length (Can't take log of -0.364299 at /var/www/dev/ofcom-document-generator.cgi line 3358.). A little example of the &conflict_check; :


Code
sub conflict_check { 
if (($FREQUENCY eq '7') && ($SITE_A_ANTENNA_LENGTH eq '0.3')) {
next;
}
if (($FREQUENCY eq '7') && ($SITE_B_ANTENNA_LENGTH eq '0.3')) {
next;
}
if (($FREQUENCY eq '11') && ($SITE_A_ANTENNA_LENGTH eq '0.3')) {
next;
}
if (($FREQUENCY eq '11') && ($SITE_B_ANTENNA_LENGTH eq '0.3')) {
next;
}
if (($FREQUENCY eq '28') && ($SITE_A_ANTENNA_LENGTH eq '0.8')) {
next;
}
if (($FREQUENCY eq '28') && ($SITE_B_ANTENNA_LENGTH eq '0.8')) {
next;
}
...and so on...


It is of my understanding that the next; should exit the current while (or foreach) and so should not process any of the other subroutine calls, therefore should not attempt to `log` the number which is usually a minus.

The two inner most foreach's do work if they are foreach's and not while's as earlier noted, however they seem to exit after just one loop so the only antenna length that gets calculated is 0.3. Possible lengths are 0.3, 0.6, 0.8, 1.0 and 1.2 for both site A and site B.

Frequency SQL query outputs:
7, 11, 13, 15, 18, 23, 26, 28, 38

Channel Width SQL query outputs:
7, 14, 28, 56

I have put all 4 SQL queries into Perl arrays and referenced them that way, but it has not changed anything, they behave in the same way as with SQL query outputs.

Many thanks to anyone who can shed any light onto the situation.

Kind regards,
Ben


(This post was edited by _Chipwiz_Ben_ on Jun 1, 2011, 9:18 AM)


BillKSmith
Veteran

Jun 1, 2011, 1:49 PM

Post #2 of 9 (1948 views)
Re: [_Chipwiz_Ben_] Nested While Loops, foreach and next [In reply to] Can't Post

next only works in the current block.

Change your call to &conflict_check to


Code
next if &conflict_check



and the subroutine to


Code
    if ( ( $FREQUENCY eq '7' ) && ( $SITE_A_ANTENNA_LENGTH eq '0.3' ) ) { 
return 1;
}
if ( ( $FREQUENCY eq '7' ) && ( $SITE_B_ANTENNA_LENGTH eq '0.3' ) ) {
return 1;
}
if ( ( $FREQUENCY eq '11' ) && ( $SITE_A_ANTENNA_LENGTH eq '0.3' ) ) {
return 1;
}
if ( ( $FREQUENCY eq '11' ) && ( $SITE_B_ANTENNA_LENGTH eq '0.3' ) ) {
return 1;
}
if ( ( $FREQUENCY eq '28' ) && ( $SITE_A_ANTENNA_LENGTH eq '0.8' ) ) {
return 1;
}
if ( ( $FREQUENCY eq '28' ) && ( $SITE_B_ANTENNA_LENGTH eq '0.8' ) ) {
return 1;
}
######... and so on ...
return 0;

Good Luck,
Bill


_Chipwiz_Ben_
Novice

Jun 2, 2011, 3:31 AM

Post #3 of 9 (1925 views)
Re: [BillKSmith] Nested While Loops, foreach and next [In reply to] Can't Post

Hi Bill,

Many thanks for your reply.

I have made the changes you suggested but the behaviour is the same. It is as if it is treating the next as a last and does not continue with other values in the foreach array.

This nested while/foreach is driving me crazyCrazy

Thanks in advance for any additional information you can offer.

Kind regards,
Ben


miller
User

Jun 2, 2011, 8:44 AM

Post #4 of 9 (1904 views)
Re: [_Chipwiz_Ben_] Nested While Loops, foreach and next [In reply to] Can't Post

Sorry mate, but I didn't have the patience to try to decipher your code. However, there's no reason that nested while and foreach loops should be giving you trouble.

If you want to use the loop operators (next, redo, continue, last) on a outer loop while in an inner one, simply add a label to the loop.


Code
OUTER: for my $outer (1..10) { 
for my $inner (1..10) {
next OUTER if $outer + $inner > 10;
printf "%s + %s = %s\n", $outer, $inner, $outer + $inner;
}
}



BillKSmith
Veteran

Jun 2, 2011, 10:36 AM

Post #5 of 9 (1897 views)
Re: [_Chipwiz_Ben_] Nested While Loops, foreach and next [In reply to] Can't Post

Miller's suggestion to label the target of the next is a good idea even if it is the innermost loop.

I understand you to mean that 'next' should abort only the current iteration of the innermost (B antenna) loop. You believe that it acts like 'last' (which would abort the current B antenna and continues with the next iteration of the A antenna loop). I suspect an error in your testing method. How do you know what happened?

It would help to know if the problem is in the main program or the subroutine. Temporarily remove the "next if...;" statement and the call to the routine which throws the exception. If all the loops run to completion, the error must be in one of the subroutines. If they do not, the error is in the main program, but has nothing to do with the next.
Good Luck,
Bill


BillKSmith
Veteran

Jun 2, 2011, 11:16 AM

Post #6 of 9 (1895 views)
Re: [BillKSmith] Nested While Loops, foreach and next [In reply to] Can't Post

The error is in your data base access! You only querry each set of data once and do not save it. I recommend reading all of the data with four calls to fetchall_array_ref, one for each of the four queries. Use four nested foreach loops to process the data. These loops would not use any DBI methods.
Good Luck,
Bill


_Chipwiz_Ben_
Novice

Jun 3, 2011, 3:47 AM

Post #7 of 9 (1861 views)
Re: [BillKSmith] Nested While Loops, foreach and next [In reply to] Can't Post

Hi all,

Thank you to all that offered assistance. I did eventually find the problem and fix it - I am quite embarrassed to admit what it was but I feel obliged to for thread completeness.

An extract from sub conflict_check:


Code
if (($FREQUENCY eq '28') && ($SITE_A_ANTENNA_LENGTH eq '1')) { 
return 1;
}
if (($FREQUENCY eq '28') && ($SITE_B_ANTENNA_LENGTH eq '1')) {
return 1;
}
if (($FREQUENCY eq '38') && ($SITE_A_ANTENNA_LENGTH eq '1')) {
return 1;
}
if (($FREQUENCY eq '38') && ($SITE_B_ANTENNA_LENGTH eq '1')) {
return 1;
}


Rows returned by MySQL for Antenna Lengths:
0.3, 0.6, 0.8, 1.0 and 1.2

That'll teach me for using eq instead of = Blush

Cheers,
Ben


(This post was edited by _Chipwiz_Ben_ on Jun 3, 2011, 3:49 AM)


miller
User

Jun 6, 2011, 3:50 PM

Post #8 of 9 (1846 views)
Re: [_Chipwiz_Ben_] Nested While Loops, foreach and next [In reply to] Can't Post

You have an answer, so this may be useless to you, but your 4 if statements can be compressed into a single conditional.


Code
if (grep {$FREQUENCY eq $_} (28,38) and ($SITE_A_ANTENNA_LENGTH eq '1' || $SITE_B_ANTENNA_LENGTH eq '1')) { 
return 1;
}


- Miller


_Chipwiz_Ben_
Novice

Jun 7, 2011, 2:16 PM

Post #9 of 9 (1838 views)
Re: [miller] Nested While Loops, foreach and next [In reply to] Can't Post

Hi Miller,

Thanks for the tips.

Kind regards,
Ben

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives