Jump to content

Barand

Moderators
  • Posts

    24,563
  • Joined

  • Last visited

  • Days Won

    822

Everything posted by Barand

  1. Consider a student who has a maths exam at the end of each term. They score 60% in each of the first 2 terms but they are ill for the third so no score can be entered. If the "score" column in the result table is defined score int NOT NULL DEFAULT '0' then not inputting the score inserts a value of 0%. When the average score is calculated at the end of the year it is 40% ((60 + 60 + 0) / 3). On the other hand, if it is defined as score int thus allowing a NULL value if omitted, the the average is a much fairer 60% ((60 + 60) / 2). Consider NULL to be the absence of known value. Use NOT NULL when it is mandatory that a value is provided.
  2. Because your table has 8 columns but you only want to insert into 3 of them, it will attempt to insert NULL values (or the columns' specified default values) into the remaining 5. Therefore, if a column is specified as NOT NULL, it should have a default value if you don't always populate it when inserting a new record. In addition, the id column should be an auto_incremented INT value by default and also excluded from the insert.
  3. The advantage of SVG (Scalable Vector Graphics) is that, as the name implies, they are scalable. Resizing should not separate the elements. Take this example svg <svg width='100%' viewBox='0 0 100 100' > <circle cx='30' cy='30' r='25' fill='#333'/> <circle cx='70' cy='70' r='25' fill='#333'/> <line x1='30' y1='30' x2='70' y2='70' stroke='#333' stroke-width='8'/> </svg> The viewBox defines the source coordinate system, the width defines the output size. If I output the same image into two differently sized containers, the image expands to fit. EG <?php $svg = "<svg width='100%' viewBox='0 0 100 100' > <circle cx='30' cy='30' r='25' fill='#333'/> <circle cx='70' cy='70' r='25' fill='#333'/> <line x1='30' y1='30' x2='70' y2='70' stroke='#333' stroke-width='8'/> </svg> "; ?> <!DOCTYPE html> <html lang='en'> <meta charset='utf-8'> <head> <title>Example</title> </head> <body> <div style='width:20%'> <?=$svg?> </div> <div style='width:50%'> <?=$svg?> </div> </body> </html> You just need to to create all your connected cells inside a single SVG image. I have been having a go at this grid problem myself and now have version which has just created 500 unique 6x5 grid maps with no circular routes and no isolated groups of cells. Each time you try to connect two cells it first verifies that it will not result in a circular path. It also verifies that all cells are reachable from any other cell. The paths through the maps are saved to a database and the path is defined as UNIQUE to ensure no repeats are saved. My grid table is like this... Code... <?php require 'db_inc.php'; $pdo = mdbConnect('db1'); $invalid = 0; $num_maps_required = 500; // if 1 is required it is displayed. If multiple they as saved to database $gridWidth = 6; $gridHeight = 5; for ($g=0; $g<$num_maps_required; $g++) { ################################################################################ # BUILD THE GRID SQUARES ################################################################################ // Grid settings $svgSize = 100; $svgColor = '#333'; // Images (Icons) $iconExit = '&#128274;'; // Shows a lock $iconMonster = '&#129430;'; // Shows a dinosaur $iconStart = '&#128578;'; // Shows a smiley $iconTreasure = '&#127873;'; // Shows a gift // Calculate Monsters $monsters = ceil($gridHeight * $gridWidth * 0.15); // Calculate Treasures $treasures = floor($gridHeight * $gridWidth * 0.25); // Make iconBox and shuffle $iconBox = array_merge( array_fill(0, $treasures, $iconTreasure), array($iconExit), array_fill(0, $monsters, $iconMonster), array($iconStart), array_fill(0, $gridHeight * $gridWidth - $monsters - $treasures - 2, '') ); shuffle($iconBox); $cells = []; foreach ($iconBox as $k => $icn) { $r = intdiv($k, $gridWidth); $c = $k % $gridWidth; $poss = [ $k-$gridWidth, $k-1, $k+1, $k+$gridWidth ]; if ($r == 0) unset($poss[0]); if ($r == $gridHeight - 1) unset($poss[3]); if ($c == 0) unset($poss[1]); if ($c == $gridWidth - 1) unset($poss[2]); $cnx = array_fill_keys($poss, 0); $cells[] = [ 'icon' => $icn, 'cnxs' => $cnx, 'reachable' => [] ]; } ################################################################################ # RANDOMLY CREATE A LINK BETWEEN EACH PAIR OF ADJACENT COLUMNs AND # ONE OR TWO LINKS BETWEEN EACH PAIR OF ADJACENT ROWS. ################################################################################ $rows = range(0, $gridHeight-1); $cols = range(0, $gridWidth-2); shuffle($rows); foreach ($cols as $c) { $r = array_pop($rows); $s = $r * $gridWidth + $c; $e = $s + 1; connectCells($s, $e, $cells); } $rows = range(0, $gridHeight-2); $cols = range(0, $gridWidth-1); shuffle($cols); foreach ($rows as $r) { for ($i=0; $i<rand(1,2); $i++) { $c = array_pop($cols); $s = $r * $gridWidth + $c; $e = $s + $gridWidth; connectCells($s, $e, $cells); } } ################################################################################ # FIND THE UNCONNECTED CELLS AND CONNECT THEM TO THEIR NEIGHBOURS # -- NOTE coonectCells() CHECKS NO CIRCULAR PATH IS CREATED ################################################################################ # $loneCells = array_filter($cells, fn($v)=>empty(array_filter($v['cnxs']))); $loneCells = array_filter($cells, fn($v)=>count(array_filter($v['cnxs'])) < 2 ); uasort($loneCells, fn($a, $b)=>rand(0,1)? -1: 1); foreach ($loneCells as $start => $lc) { foreach ($lc['cnxs'] as $end => $v) { if (!$v ) { connectCells($start, $end, $cells); } } } ################################################################################ # MAP NOW GENERATED # - VERIFY # - SAVE THE ROUTES THROUGH THE MAZE FOR SUBSEQUENT ANALYSIS # - PRINT THE MAP ################################################################################ $cells[0]['reachable'] = []; findReachable(0, $cells, $cells[0]['reachable']); $pathLength = count($cells[0]['reachable']); $path = join(', ', $cells[0]['reachable']); if ($pathLength != $gridHeight * $gridWidth) { ++$invalid; echo "<h1>INVALID GRID MAP $invalid</h1>" ; echo "$pathLength cells: $path<br>"; } else switch ( $num_maps_required ) { case 1: echo printMap($gridHeight, $gridWidth, $cells); break; default: saveMap($pdo, $gridHeight, $gridWidth, $path, $pathLength, $cells); break; } } ################################################################################ # FUNCTIONS ################################################################################ function saveMap(PDO $pdo, $gridHeight, $gridWidth, $path, $pathLength, &$cells) { $pdo->beginTransaction(); try { $stmtg = $pdo->prepare("INSERT IGNORE INTO grid (height, width, path, path_length) VALUES (?, ?, ?, ?)"); $stmtgc = $pdo->prepare("INSERT INTO grid_cell (grid_id, cell_no, icon) VALUES (?, ?, ?)"); $stmtcnx = $pdo->prepare("INSERT INTO cell_cnx (grid_id, from_cell, to_cell) VALUES (?, ?, ?)"); $stmtg->execute( [ $gridHeight, $gridWidth, $path, $pathLength ] ); $grid_id = $pdo->lastInsertId(); #TODO grid_cell table, cell_cnx table foreach ($cells as $cno => $cl) { $stmtgc->execute( [ $grid_id, $cno, $cl['icon'] ] ); foreach ($cl['cnxs'] as $k => $v) { if ($v && $k > $cno) { $stmtcnx->execute( [ $grid_id, $cno, $k ] ); } } } $pdo->commit(); } catch(PDOException $e) { $pdo->rollBack(); throw $e; } } /** * Recursively searches all possible paths through the maze from start * and stores new reachable cells in array * * @param int $from starting cell * @param array pointer $cells cells array * @param array pointer $reachable all reachable cells */ function findReachable($from, &$cells, &$reachable) { foreach ($cells[$from]['cnxs'] as $k => $v) { if ($v) { if (!in_array($k, $reachable)) { $reachable[] = $k; findReachable($k, $cells, $reachable); } } } } function connectCells($start, $end, &$cells) { $cells[$end]['reachable'] = []; findReachable($end, $cells, $cells[$end]['reachable']); # # if cell is already reachable then connecting to it would result in a circular path # if (in_array($start, $cells[$end]['reachable'])) { return 0; } $cells[$start]['cnxs'][$end] = 1; $cells[$end]['cnxs'][$start] = 1; return 1; } function printMap ($rows, $cols, &$cells) { $cellSize = 80; $cellBgd = '#333'; $wid = $cols * $cellSize; $ht = $rows * $cellSize; $ix = 10; $iy = 10; $cx = $cy = $cellSize/2; $isz = $cellSize - 20; $ty = 47; $ty2 = $cellSize - 14; $svg = "<svg width='$wid' viewBox='0 0 $wid $ht'> <rect x='0' y='0' width='$wid' height='$ht' fill='linen' /> "; foreach ($cells as $k => $cell) { $transx = $k % $cols * $cellSize; $transy = intdiv($k, $cols) * $cellSize; $sColor = count(array_filter($cell['cnxs']))==1 ? '#aaa' : $cellBgd; $svg .= "<g transform='translate($transx, $transy)' > <rect x='$ix' y='$iy' width='$isz' height='$isz' rx='8' ry='8' fill='$cellBgd' stroke='$sColor' stroke-width='2'/> "; foreach ($cell['cnxs'] as $c => $connected) { if ($c > $k && $connected) switch ($c - $k) { case 1: $svg .= "<path d='M $cx $cy h $cellSize' stroke='$cellBgd' stroke-width='10' />\n"; break; case $cols: $svg .= "<path d='M $cx $cy v $cellSize' stroke='$cellBgd' stroke-width='10' />\n"; break; } } $svg .= "<text x='$cx' y='$ty' font-size='24px' fill='#FFF' text-anchor='middle'>{$cell['icon']}</text> <text x='$cx' y='$ty2' font-size='12px' fill='#FFF' text-anchor='middle'>$k</text> </g> "; } $svg .= "</svg>\n"; return $svg; } ?> The next step is to be able to select a stored grid map from the DB and display it.
  4. Then you should have mentioned that at the start instead of wasting our time on a different problem. Try experimenting.
  5. My code... <!DOCTYPE html> <html lang='en'> <meta charset='utf-8'> <head> <title>Example</title> <style type="text/css"> body { font-family: verdana, sans-serif; font-size: 12pt; padding: 20px; } h2 { font-variant: small-caps; text-align: center; } .chapter { width: 100%; margin-top: 20px; margin-bottom: 20px; border-bottom: 5px solid blue; text-align: center; } .head-text { display: inline; padding: 0 10px; background-color: white; font-family: gabriola, cursive; font-size: 20pt; font-style: italic; font-weight: 600; position: relative; top: +26px; } p { text-align: justify; line-height: 22px; } </style> </head> <body> <h2>Book 3</h2> <div> <div class='chapter'> <div class='head-text'> Caput vigesimum septimum </div> </div> <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna. </p> <p>Suspendisse dui purus, scelerisque at, vulputate vitae, pretium mattis, nunc. Mauris eget neque at sem venenatis eleifend. Ut nonummy. Fusce aliquet pede non pede. Suspendisse dapibus lorem pellentesque magna. Integer nulla. Donec blandit feugiat ligula. Donec hendrerit, felis et imperdiet euismod, purus ipsum pretium metus, in lacinia nulla nisl eget sapien. Donec ut est in lectus consequat. </p> <div class='chapter'> <div class='head-text'> Epilogus </div> </div> <p>Nunc viverra imperdiet enim. Fusce est. Vivamus a tellus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci. Aenean nec lorem. In porttitor. Donec laoreet nonummy augue. </p> </div> </body> </html>
  6. If I still have the code, I'll post it. However, as you are well aware, it can sometimes take weeks to complete the labour-intensive task of answering a post.
  7. Give us a clue! We need more than that if we're to help. Perhaps give examples of what you have now, and what you want
  8. Why explode on comma when they too are delimited by '|||' ? If that is the case (although your example says otherwise) then you can use array_combine() to store the related values EG $p_id = "1.1.51|||1.1.51.2|||1.1.51.3|||1.1.51.4|||1.1.51.5|||1.1.51.6|||1.1.51.7|||1.1.51.8|||1.1.51.9"; $theme = 'b|||c|||d|||e|||f|||g|||h|||i|||j'; $i = explode('|||', $p_id); $t = explode('|||', $theme); $result = array_combine($i, $t); foreach ($result as $id => $theme) { echo "$id : $theme <br>"; } giviing 1.1.51 : b 1.1.51.2 : c 1.1.51.3 : d 1.1.51.4 : e 1.1.51.5 : f 1.1.51.6 : g 1.1.51.7 : h 1.1.51.8 : i 1.1.51.9 : j
  9. Perhaps... $a = explode(',', '1.1.51,1.1.51.10,1.1.51.2,1.1.51.3,1.1.51.4,A,1.1.52'); echo 'original <pre> ' . print_r($a, 1) . '</pre>'; sort($a); echo 'after sort() <pre> ' . print_r($a, 1) . '</pre>'; natsort($a); echo 'after natsort() <pre> ' . print_r($a, 1) . '</pre>'; giving... original Array ( [0] => 1.1.51 [1] => 1.1.51.10 [2] => 1.1.51.2 [3] => 1.1.51.3 [4] => 1.1.51.4 [5] => A [6] => 1.1.52 ) after sort() Array ( [0] => 1.1.51 [1] => 1.1.51.10 [2] => 1.1.51.2 [3] => 1.1.51.3 [4] => 1.1.51.4 [5] => 1.1.52 [6] => A ) after natsort() Array ( [0] => 1.1.51 [2] => 1.1.51.2 [3] => 1.1.51.3 [4] => 1.1.51.4 [1] => 1.1.51.10 [5] => 1.1.52 [6] => A )
  10. Does it work with $DB_ENCODING = 'utf8';
  11. Try a ... <html> <head> </head> <body> </body> </html> ... structure instead of your pick'n'mix approach to the documant sections. (And why was this posted in PHP Coding Help forum?)
  12. Use code blocks when posting code (the <> button)
  13. I'd start by checking what data contains with console.log(data)
  14. To add a listener to an element, the element must exist. Make sure you add the listeners after the elements have been created.
  15. That's the thing about programming - it does what you tell it to do. You told it to respond to clicks inside the div. Try document.getElementByTagName("input").addEventListener("click", displayDate); function displayDate() { alert('Hurray'); }
  16. As you have it now but make the <select> required (to force a values other than "") <select name="cars" id="cars" required> <option value="" >Car choices</option> <option value="volvo">Volvo</option> <option value="saab">Saab</option> </select>
  17. Judicious application of array key names can greatly increase the efficiency and simplicity of your code. Consider this simplified version of the questions/options form code <form method='post' > <?php for ($qno=1; $qno<=2; $qno++) { echo <<<HTML <label> Sub Question $qno <span class="req">*</span> <textarea cols="46" rows="3" name="Q[$qno][question]" placeholder="Enter Sub question here.."></textarea> </label> <ul> HTML; for ($opt='A'; $opt<='D'; $opt++) { echo <<<HTML <li>Choice $qno$opt (text)&nbsp; <input type='text' name="Q[$qno][opts][$opt]" placeholder="Enter Choice A here.." size='40'> </li><br><br>\n HTML; } echo "</ul><hr>\n"; } ?> <input type='submit'> </form> producing... When the form is submitted, the POST array is like this... Array ( [Q] => Array ( [1] => Array ( [question] => aaaaaaaaaaaaaaaaaaaaaaaaaaa [opts] => Array ( [A] => aa [B] => bb [C] => cc [D] => dd ) ) [2] => Array ( [question] => bbbbbbbbbbbbbbbbbbbbbbbbb [opts] => Array ( [A] => ww [B] => xx [C] => yy [D] => zz ) ) ) ) Now you can easily iterate through the array to write the questions/options to you database foreach ( $_POST['Q'] as $qno => $qdata ) { write $qno and $qdata['question'] to question table save last insert id as $qid foreach ( $qdata['opts'] as $ono => $choice ) { write $qid, $ono, $choice to choice table } } Job Done.
  18. Almost 5,000 chars of unformatted html! TLDR
  19. Use join() instead of the foreach loop. echo join(':', $numbers);
  20. Let me introduce you to the reference manual. See https://www.php.net/mysqli_fetch_array
  21. mysqli_fetch_array() does not return the number of rows To do that you would need to remove and authorized ='1' and add "authorized" to the selected columns. Then check if $num['authorized'] == 1 (or not).
  22. To do this you would use a SQL query to match A's preferences against B's profile and return all matching Bs To do this you would use a SQL query to match A's profile against B's preferences to see if A can view B
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.