Website đƣợc thiết kế bao gồm 3 trang giao diện chính: sự kiện, nhân vật và địa điểm. Mối liên kết giữa 3 trang này đƣợc tóm tắt qua sơ đồ sau:
Hình 1. Mối liên kết giữa 3 trang sự kiện, nhân vật và địa điểm
3.1 Xây dựng trang sự kiện
Hình 2. Cấu trúc trang sự kiện 3.1.1 Xây dựng khung thời gian
Trong khung thời gian, người dùng có thể truy cập từ tổng quát đến chi tiết, từ giai đoạn lớn đến các giai đoạn nhỏ hơn và từ đó đến các sự kiện lịch sử cụ thể .
Hình 3. Hướng truy cập vào các sự kiện lịch sử
Các đoạn code sau sẽ cho phép thực hiện các bước truy cập trên.
1. <?php
2. $chuoi=basename($_SERVER['SCRIPT_NAME']);
3. $lenchuoi= strlen($chuoi);
4. if ($lenchuoi==16) {$masub=substr($chuoi,11,1);}
5. if ($lenchuoi==17) {$masub=substr($chuoi,11,2);}
6. if ($lenchuoi==18) {$masub=substr($chuoi,11,1);}
7. if ($lenchuoi==19) {$masub=substr($chuoi,11,1);}
8. if ($lenchuoi>19) {$masub=substr($chuoi,11,1);}
9. if ($lenchuoi==9) {$masub=0;}
10. ?>
Câu lệnh dòng 2 sẽ trả về tên của file php hiện hành trên cửa sổ trình duyệt.
Tên file php đƣợc đặt tên theo nguyên tắc: sukienn_subx.php, với x là thứ tự các giai đoạn nhỏ trong giai đoạn 1939 – 1945.
Câu lệnh dòng 3 sẽ trả về độ dài của tên file php.
Các câu lệnh từ 4 đến 9 sẽ kiểm tra độ dài chuỗi, lấy ra giá trị của x chứa trong biến $masub tương ứng với từng độ dài chuỗi của từng file php hiện hành.
11. <?php if ($masub==1 or $masub==2 ) {echo ' <span> ';} ?>Giai đoạn 1919 - 1930
<?php if ($masub==1 or $masub==2 ) {echo ' </span> ';} ?>
12. <?php
13. $tb1=mysql_query("select
sub.magd_sub,sub.tengiaidoan,sub.nambatdau,sub.namketthuc,sub.link from giaidoan_sub sub,giaidoan_main main where sub.magdmain=main.magdmain and main.magdmain='1'") ;
14. while($row = mysql_fetch_array($tb1)) 15. {
16. ?>
17. <li ><a href=<?php echo $row["link"]; ?> >
18. <?php if ($row["magd_sub"]==$masub) {echo $row["tengiaidoan"]." từ năm ". $row["nambatdau"]." đến năm ".$row["namketthuc"];
19. ?> <img src="images/yellow-star.gif">
20. <?php } ?>
21. <?php
22. if ($row["magd_sub"]!=$masub) {echo $row["tengiaidoan"]." từ năm ".
$row["nambatdau"]." đến năm ".$row["namketthuc"];}
23. ?>
24. </a></li>
25. <?php 26. } 27. ?>
28. <?php
29. $tb6=mysql_query("select
sk.magd_sub,sk.masukien,sk.tensukien,sk.ngaybatdau,sk.ngayketthuc ,sk.thangbatdau,sk.nambatdau,sk.thangketthuc,sk.namketthuc,sk.link from sukien sk,giaidoan_sub sub
where sk.magd_sub=sub.magd_sub and sk.magd_sub='".$masub."'
order by sk.nambatdau,sk.thangbatdau,sk.ngaybatdau,
sk.namketthuc,sk.thangketthuc,sk.ngayketthuc ASC") ; 30. while($row = mysql_fetch_array($tb6))
31. { 32. ?>
Câu lệnh thứ 11 kiểm tra giá trị của $masub, nếu giá trị của $masub = 1 hoặc $masub=2 tương ứng với các giai đoạn có mã số là 1 và 2 thì sẽ in ra kết quả là thuộc giai đoạn lớn 1919 – 1930.
Câu lệnh thứ 13 là câu truy vấn SQL từ CSDL MySQL để chọn ra các giai đoạn lịch sử nhỏ trong giai đoạn 1919 – 1930 có mã số =1 (main.magdmain='1' ).
Câu lệnh 14 đến 17 sẽ kiểm tra câu truy vấn trên, nếu thõa điều kiện sẽ gán đường dẫn liên kết đến trang web chứa nội dung tương ứng của từng giai đoạn nhỏ. Các đường dẫn này được chứa trong cột [link] trong bảng giaidoan_sub trong CSDL MySQL.
Câu lệnh 18 đến 26 sẽ lấy kết quả từ câu truy vấn và hiển thị tên, năm bắt đầu và năm kết thúc của từng giai đoạn nhỏ
Câu lệnh từ 28 đến 32 sẽ truy vấn và hiển thị các sự kiện chi tiết hơn trong giai đoạn nhỏ đƣợc chọn.
Các giai đoạn còn lại được viết code tương tự như trên.
3.1.2 Xây dựng công cụ tìm kiếm sự kiện
Website hỗ trợ người dùng tìm kiếm theo hai cách: theo giai đoạn lịch sử và theo từ khóa.
Tìm kiếm theo giai đoạn lịch sử
Công cụ này cho phép người sử dụng chọn năm bắt đầu và năm kết thúc, kết quả tìm kiếm sẽ hiển thị và cho phép người dùng truy cập đến các sự kiện nằm trong giới hạn khoảng cách năm được chọn trước đó.
Hình 4. Giải thuật xây dựng công cụ tìm kiếm theo giai đoạn lịch sử Đoạn code thực hiện tìm kiếm theo giai đoạn lịch sử bao gồm 2 phần.
Phần 1: cho phép người dùng nhập năm bắt đầu và năm kết thúc
1
<table class="table_inputnam">
2 <form method="post" action="sukienn_search_time_resuft.php" target="bank" id="searchform">
3 <tr >
4 <td> Chọn năm bắt đầu</td>
5 <td>
6 <select name="year_bd">
7 <?php
8 $dbcon=mysql_connect("localhost","root","");
9 mysql_select_db("lichsuvn",$dbcon) or die("khong the ket noi database");
10
$tb=mysql_query("select sub.nambatdau from giaidoan_sub sub order by sub.nambatdau") or die("could noi connect");
11 while ($kq=mysql_fetch_assoc($tb)) {
12 // echo "<option value=".$kq["tenhuyen"].">".$kq["tenhuyen"]."</option>";
13 echo "<option value='".$kq["nambatdau"]."'>".$kq["nambatdau"]."</option>";
14 } 15 ?>
16 </select>
17 </td>
18 <td> Chọn năm kết thúc</td>
19 <td>
20 <select name="year_kt">
21 <?php
22 $dbcon=mysql_connect("localhost","root","");
23 mysql_select_db("lichsuvn",$dbcon) or die("khong the ket noi database");
24
$tb=mysql_query("select sub.namketthuc from giaidoan_sub sub order by sub.namketthuc") or die("could noi connect");
25 while ($kq=mysql_fetch_assoc($tb)) {
26 // echo "<option value=".$kq["tenhuyen"].">".$kq["tenhuyen"]."</option>";
27 echo "<option value='".$kq["namketthuc"]."'>".$kq["namketthuc"]."</option>";
28 } 29 ?>
30 </select>
31 </td>
32 <td><input type="submit" name="submit" value="Tìm kiếm"></td>
33 </tr>
34 </form>
35 </table>
Phần 2: Kiểm tra điều kiện và hiển thị kết quả tìm kiếm
1 <?php 2
//lấy giá trị của người dùng đã chọn cho năm bắt đầu và năm kết thúc
$nambatdau=addslashes($_POST["year_bd"]);
3 $namketthuc=addslashes($_POST["year_kt"]);
4 $where1="1=1";
5 $where2="1=1";
6
// so sánh điều kiện
if($nambatdau<>"" and $namketthuc<>"" and $namketthuc <= $nambatdau) { 7
echo '<h2 class="tieude_search"> Vui lòng chọn lại <span>năm bắt đầu </span> và
<span>năm kết thúc </span> </h2>';
8 }
9 if($nambatdau<>"" and $namketthuc<>""){
10 $where1=$where1. " and sub.nambatdau >=".$nambatdau;
11 $where2=$where2." and sub.namketthuc <=".$namketthuc;
12 } 13
// kết nối với CSDL MySQL
$dbcon=mysql_connect("localhost","root","");
14 mysql_select_db("lichsuvn",$dbcon) or die("khong the ket noi database");
15 mysql_set_charset('utf8',$dbcon);
16
$query = "select
sk.tensukien,sk.ngaybatdau,sk.thangbatdau,sk.nambatdau,sk.ngayketthuc,sk.thangket thuc,sk.namketthuc,sk.link from giaidoan_sub sub, sukien sk where ".$where1." and
".$where2." and sk.magd_sub=sub.magd_sub";
17
echo '<h2 class="tieude_search"> Bạn đang tìm các sự kiện trong giai đoạn từ
<span>'.$nambatdau. ' </span> đến năm <span>'.$namketthuc. '</span></h2>' ; 18 $result = mysql_query($query);
19 ?>
20
<table width="100%" border="0" cellpadding="5" bordercolor="#FF0000"
cellspacing="5" class="table_kq">
21 <tr>
22 <td width="60%" class="td" >Tên sự kiện</td>
23 <td width="20%" class="td" >Ngày bắt đầu</td>
24 <td width="20%" class="td" >Ngày kết thúc</td>
25 </tr>
26 <?php
27 // Hiển thị kết quả
28 while ($row= mysql_fetch_array($result)) 29 {
30 ?>
31 <tr>
32 <td> <a href= <?php echo $row["link"]; ?> ><?php 33 echo $row["tensukien"]; ?> </a></td>
34 <td Align="center"> <?php 35
if (isset($row["ngaybatdau"]) and isset($row["thangbatdau"]) and isset($row["nambatdau"]) )
36 {echo $row["ngaybatdau"]."/".$row["thangbatdau"]."/".$row["nambatdau"];}
37 elseif (isset($row["thangbatdau"]) and isset($row["nambatdau"]) ) 38 {echo $row["thangbatdau"]."/".$row["nambatdau"];}
39 elseif (isset($row["nambatdau"]) ) 40 {echo $row["nambatdau"];}
41 ?></td>
42 <td Align="center"> <?php
isset($row["namketthuc"]) )
44 {echo $row["ngayketthuc"]."/".$row["thangketthuc"]."/".$row["namketthuc"];}
45 elseif (isset($row["thangketthuc"]) and isset($row["namketthuc"]) ) 46 {echo $row["thangketthuc"]."/".$row["namketthuc"];}
47 elseif (isset($row["namketthuc"]) ) 48 {echo $row["namketthuc"];}
49 ?></td>
50 </tr>
51 <?php 52 } 53 ?>
Tìm kiếm theo từ khóa
Công cụ này cho phép người sử dụng tìm kiếm các sự kiện bằng cách nhập từ khóa vào ô tìm kiếm. Từ khóa này đƣợc so sánh với tên các sự kiện trong CSDL MySQL, kết quả sẽ hiển thị và cho phép người sử dụng truy cập vào các sự kiện có chứa các từ khóa được nhập bởi người dùng.
Hình 5. Giải thuật xây dựng công cụ tìm kiếm theo từ khóa
Đoạn code thực hiện tìm kiếm có nội dung nhƣ sau:
1 <?php
2 if(isset($_POST['submit'])) {
3 $errors=array();
4 $required=array('name');
5 foreach($required as $fieldname) {
6 if(!isset($_POST[$fieldname]) || empty($_POST[$fieldname])) {
7
8 }
9 }//End : foreach
10
11 if(empty($errors)) {
12 // Kết nối tới CSDL
13 $dbcon=mysql_connect("localhost","root","");
14 mysql_select_db("lichsuvn",$dbcon) or die("khong the ket noi database");
15 mysql_set_charset('utf8',$dbcon);
16 //if( isset($_POST['submit']) ) 17 //{
18 $var = $_POST['name'];
19 // so sánh tên sự kiện với từ khóa nhập vào
20 $query = "select * from sukien where tensukien like '%$var%' order by tensukien";
21 $result = mysql_query($query);
22 $numrows=mysql_num_rows($result);
23 if ($numrows == 0)
24 {
25 echo "Kết quả";
26 echo "Xin lỗi không tìm thấy " .$var. " trong cơ sở dữ liệu";
27 exit; //
28 }
29 // Dùng vòng lặp while để in tên sự kiện thỏa điều kiện 30 while ($r= mysql_fetch_array($result))
31 {
32 $faq_id = $r['tensukien'];
33 echo '<ul>';
34 ?>
35
<a class="sucess" href= <?php echo $r["link"]; ?> ><?php echo '<li>'.$r['tensukien'].'</li>'; ?></a>
36 <?php
37 echo '</ul>';
38 }
39 } //end empty(errors)
40 }//End: isset($POST['submit'])) 41 ?>
43 if (!empty($errors)) { 44 //echo "<ul>";
45 foreach ($errors as $error) {
46 echo"$error";
47 }
48 //echo "</ul>";
49 } 50 ?>
3.1.3 Xây dựng bản đồ minh họa cho các sự kiện lịch sử
Bản đồ lịch sử trong Website đƣợc xây dựng bằng công nghệ WebGIS mã nguồn mở, các bước thực hiện được thể hiện qua sơ đồ sau:
Hình 6. Các bước xây dựng bản đồ lịch sử
Trực quan hóa dữ liệu
Trực quan hóa dữ liệu là quá trình chọn lọc cách thức thể hiện nội dung lịch sử lên bản đồ. Quá trình này được thực hiện bằng cách phương pháp lập trình bằng ngôn ngữ SLD. Geosever hỗ trợ ngôn ngữ SLD cũng như đưa ra đầy đủ các hướng dẫn về cách thức thể hiện nội dung lên bản đồ bằng ngôn ngữ này.
Sau đây là một số ví dụ cho việc hiển thị trực quan dữ liệu bằng ngôn ngữ SLD.
Hiển thị trực quan cho dữ liệu dạng vùng
1 <?xml version="1.0" encoding="UTF-8"?>
2
<StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1.0"
xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd"
xmlns:se="http://www.opengis.net/se">
3 <NamedLayer>
4 <se:Name>daiduong</se:Name>
5 <UserStyle>
6 <se:Name>daiduong</se:Name>
7 <se:FeatureTypeStyle>
8 <se:Rule>
9 <se:Name>Single symbol</se:Name>
10 <se:PolygonSymbolizer>
11 <se:Fill>
12 <se:SvgParameter name="fill">#82c9ff</se:SvgParameter>
13 </se:Fill>
14 <se:Stroke>
15 <se:SvgParameter name="stroke">#82c9ff</se:SvgParameter>
16 <se:SvgParameter name="stroke-width">0.26</se:SvgParameter>
17 </se:Stroke>
18 </se:PolygonSymbolizer>
19 </se:Rule>
20 </se:FeatureTypeStyle>
21 </UserStyle>
22 </NamedLayer>
23 </StyledLayerDescriptor>
Câu lệnh 4 đặt xác định lớp dữ liệu cần hiển thị. Tên của lớp dữ liệu đƣợc đặt trong cặp lệnh <se:Name>
Câu lệnh từ 8 đến 19 xác định các cách (rule) để hiển thị dữ liệu. Cặp lệnh
<se:Name>Single symbol</se:Name> xác định chọn cách thể hiện giống nhau (Single symbol) cho toàn bộ các đối tƣợng trên bản đồ. Nội dung trong cặp lệnh <se:PolygonSymbolizer> xác định cụ thể cách thể hiện nhƣ: cặp lệnh <se:Fill> chọn màu nền cho vùng với mã màu là #82c9ff; cặp lệnh
<se:Stroke> quy định màu cho đường viền ("stroke">#82c9ff) và độ rộng của vùng ("stroke-width">0.26).
Thực hiện tương tự với lớp dữ liệu dạng đường và dạng điểm.
Hiển thị trực quan cho lớp dữ liệu dạng đường
1 <?xml version="1.0" encoding="UTF-8"?>
2
<StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1.0"
xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd"
xmlns:se="http://www.opengis.net/se">
3 <NamedLayer>
4 <se:Name>vn_giaothong</se:Name>
5 <UserStyle>
6 <se:Name>vn_giaothong</se:Name>
7 <se:FeatureTypeStyle>
8 <se:Rule>
9 <se:Name>Single symbol</se:Name>
10 <se:LineSymbolizer>
11 <se:Stroke>
12 <se:SvgParameter name="stroke">#d9a388</se:SvgParameter>
13 <se:SvgParameter name="stroke-width">0.26</se:SvgParameter>
14 <se:SvgParameter name="stroke-linejoin">bevel</se:SvgParameter>
15 <se:SvgParameter name="stroke-linecap">square</se:SvgParameter>
16 <se:SvgParameter name="stroke-opacity">0.4</se:SvgParameter>
17 </se:Stroke>
18 </se:LineSymbolizer>
19 </se:Rule>
20 </se:FeatureTypeStyle>
21 </UserStyle>
22 </NamedLayer>
23 </StyledLayerDescriptor>
Hiển thị trực quan với dữ liệu dạng điểm
1
<StyledLayerDescriptor xmlns="http://www.opengis.net/sld"
xmlns:ogc="http://www.opengis.net/ogc" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0.0"
xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd">
2 <NamedLayer>
3 <Name>Point as graphic</Name>
4 <UserStyle>
5 <Title>GeoServer SLD Cook Book: Point as graphic</Title>
6 <FeatureTypeStyle>
7 <Rule>
8 <PointSymbolizer>
9 <Graphic>
10 <ExternalGraphic>
11
<OnlineResource xlink:type="simple" xlink:href="hand-icon.png"/> // file ảnh hand- icon.png được tạo để làm kí hiệu được lưu trong cùng thư mục với file .sld 12 <Format>image/png</Format>
13 </ExternalGraphic>
14 <Size>25</Size>
15 </Graphic>
16 </PointSymbolizer>
17
18 </Rule>
19 </FeatureTypeStyle>
20 </UserStyle>
21 </NamedLayer>
22 </StyledLayerDescriptor>
Hiển thị dữ liệu lên Website
Giai đoạn này đƣợc thực hiện bằng cách kết hợp các hàm trong thƣ viện mã nguồn mở Openlayer và các ngôn ngữ lập trình web. Đoạn code sau sẽ thể hiện cách thức hiển thị dữ liệu lên Website.
1 <link rel="stylesheet" type="text/css" href="css/map_style.css">
2 <script src="OpenLayers/lib/Firebug/firebug.js"></script>
3
<script type="text/javascript">
// Định nghĩa một số thuộc tính chung cho các lớp bản đồ: hệ quy chiếu, giới hạn (bounds)…
4 function init(){
5 map = new OpenLayers.Map('map', { 6 target: 'map',
7
maxExtent: new OpenLayers.Bounds(406025.33734510065, 946295.1046635299, 985655.2820608318, 4587039.4253855865),
8 maxResolution: "auto", 9 projection:"EPSG:32648", 10 units: 'm',
11
displayProjection: new OpenLayers.Projection("EPSG:32648"), // Thêm các công cụ vào bản đồ
12 controls: [
13 new OpenLayers.Control.Navigation(),
14 new OpenLayers.Control.PanZoomBar({'zoomWorldIcon': true}), 15
16 new OpenLayers.Control.Permalink({anchor: true}),
17 new OpenLayers.Control.ScaleLine(), 18 new OpenLayers.Control.MousePosition(), 19 new OpenLayers.Control.OverviewMap(), 20 new OpenLayers.Control.KeyboardDefaults() 21 ],
22 numZoomLevels: 6 23 }
24
);
// Thêm khung quản lý các lớp dữ liệu vào bản đồ (Layer Control) 25
map.addControl(new
OpenLayers.Control.LayerSwitcher({'div':OpenLayers.Util.getElement('layerswitcher')}));
26
// map.addControl(new
OpenLayers.Control.Permalink({'div':OpenLayers.Util.getElement('permalink')}));
// Xác định đường dẫn đến CSDL (database) được tạo trong Geoserver 27 var urlmapfile = "http://localhost:8086/geoserver/lichsuvn/wms"
28
var format="image/png";
// Bắt đầu thêm các lớp bản đồ 31 //Thêm lớp vn_hiennay
39 vn_hiennay = new OpenLayers.Layer.WMS(
40 Ranh giới hành chính tỉnh Việt Nam hiện nay, urlmapfile, 41 {
42 LAYERS: 'lichsuvn:group_vn_tinh', 43 transparent:"true",
44 format: format 45 },
46 {singleTile: true, ratio: 1}
47 );
48 map.addLayer(vn_hiennay );
49
vn_hiennay.setVisibility(false);
// Thêm lớp vn_giaothong
60 vn_giaothong= new OpenLayers.Layer.WMS(
61 Giao thông, urlmapfile, 62 {
63 LAYERS: 'lichsuvn:vn_giaothong', 64 transparent:"true",
65 format: format 66 },
67 {singleTile: true, ratio: 1}
68 );
69 map.addLayer(vn_giaothong);
70 }
71 </script>
3.1.4 Xây dựng chức năng thống kê nhân vật và địa điểm liên quan đến sự kiện đang truy cập
Việc thống kê các nhân vật và địa điểm liên quan đến sự kiện đang truy cập nhằm giúp mở rộng thêm thông tin về sự kiện lịch sử, giúp tìm hiểu sự kiện đó một cách đầy đủ, toàn diện hơn. Đoạn code sau sẽ thực hiện chức năng này.
1 <link rel="stylesheet" type="text/css" href="css/sukienn_nhanvat_diadiem.css">
2 <?php
3
// lấy tên file trên thanh địa chỉ trình duyệt, tên file được đặt theo nguyên tắc sukienn_subx_y, với x là mã số giai đoạn nhỏ và y là mã số sự kiện được lưu trong CSDL MySQL
$chuoi=basename($_SERVER['SCRIPT_NAME']);
4
// trả về chiều dài của tên file
$lenchuoi= strlen($chuoi);
5 ?>
6
<?php
// so sánh độ dài chuỗi và lấy ra mã số sự kiện y và gán mã này cho biến $mask 8 if ($lenchuoi==16) {$mask=substr($chuoi,11,1);}
9 if ($lenchuoi==17) {$mask=substr($chuoi,11,2);}
10 if ($lenchuoi==18) {$mask=substr($chuoi,13,1);}
11 if ($lenchuoi==19) {$mask=substr($chuoi,13,2);}
12 // kết nối với CSDL
13 $dbcon=mysql_connect("localhost","root","");
14 mysql_select_db("lichsuvn",$dbcon) or die("khong the ket noi database");
15 mysql_set_charset('utf8',$dbcon);
16 ?>
17
// sử dụng câu lệnh SQL để tìm các nhân vật có liên quan đến sự kiện đang truy cập (biến
$mask)
<?php
18
$nv=mysql_query("select lk.masukien,lk.manhanvat,nv.tennhanvat,nv.link from lk_sukien_nhanvat lk, nhanvat nv,sukien sk where lk.masukien=sk.masukien and lk.manhanvat=nv.manhanvat and sk.masukien='".$mask."' order by tennhanvat ") ;
19
// vòng lặp while cho phép hiển thị các nhân vật thỏa câu truy vấn và gán đường liên kết đến trang website tương ứng với tên từng nhân vật
while($row = mysql_fetch_array($nv)) 20 {
21 ?>
22 <a href=""> <?php 23 echo '<ul>';
24 ?>
25
<a class="sucess" href= <?php echo $row["link"]; ?> > <?php echo '<li class="list_nv">'.$row["tennhanvat"].'</li>' ; ?> </a>
26 <?php 27 echo '</ul>' 28 ?>
29 <?php
<h3> Địa điểm</h3>