From 85b268c0b87a283db2dd6bb8e1b718b05343b035 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Tue, 11 Feb 2020 15:58:06 -0500 Subject: [PATCH] Rendering is mostly working. Still need to finish presenters and everything related to files. --- app/index.html | 2 + app/js/module_app_ui_v2.js | 448 +++++++++++++++++++++++-------------- config.json | 6 +- 3 files changed, 289 insertions(+), 167 deletions(-) diff --git a/app/index.html b/app/index.html index 648c7fb..bad27d4 100644 --- a/app/index.html +++ b/app/index.html @@ -428,6 +428,8 @@ safe_to_render_launcher = false; // Set to false so that the launcher render only starts after the launcher object has updated run_check_file_cache = true; // Set to true so that the local file cache will be checked against the updated event files idb_event_file_check_datetime = Date.now() + idb_event_file_check_period; + + let render_event_presenter_records_result = await uiv2.render_event_presenter_records(); // NOTE: v2 idb to ui } diff --git a/app/js/module_app_ui_v2.js b/app/js/module_app_ui_v2.js index 955bcc4..b5e58cf 100644 --- a/app/js/module_app_ui_v2.js +++ b/app/js/module_app_ui_v2.js @@ -18,18 +18,19 @@ exports.render_event_records = function () { } + +// This function is used to render all event file records to the UI. // NOTE: The event_file table should probably only be looped through once when the table is actually updated. // NOTE: Not each time the other objects (event, location, session, presentation, presenter) are updated. exports.render_event_file_records = function (event_files, event_id) { console.log('Rendering event file records...'); - /* tbl_event_file.iterate(function(value, key, iteration) { if (value.id == event_id) { - console.log('*** Event id ('+event_id+') found in table.'); + console.log('This event file ('+value.id+') is part of the this event ('+event_id+').'); document.getElementById('event_name').innerHTML = '@'+value.name; } else { - console.log('Event not it.'); + console.log('This event file ('+value.id+') is NOT part of the this event ('+event_id+').'); } }).then(function() { console.log('idb_to_ui: Iterate tbl_event_file complete') @@ -44,7 +45,7 @@ exports.render_event_file_records = function (event_files, event_id) { } document.getElementById('event_files_menu').innerHTML += ''; - */ + } @@ -115,7 +116,7 @@ exports.render_event_session_records = async function () { // Add the new session to the launcher sessions list let div_node = document.createElement('DIV'); div_node.id = 'detail_session_'+value.id; - div_node.className = 'container d-none session_detail'; + div_node.className = 'container d-none session_detail event_session'; div_node.setAttribute('data-session_id', value.id); let h2_node = document.createElement('H2'); @@ -139,19 +140,21 @@ exports.render_event_session_records = async function () { // Add placeholder cards for session files and session presentations // Files let files_div_node = document.createElement('DIV'); + files_div_node.id = 'event_session_files_'+value.id; files_div_node.className = 'card session_files'; let files_header_div_node = document.createElement('DIV'); files_header_div_node.className = 'card-header'; - let files_header_text_node = document.createTextNode('Sessions Files:'); + let files_header_text_node = document.createTextNode('Session Files:'); files_header_div_node.appendChild(files_header_text_node); let files_body_div_node = document.createElement('DIV'); files_body_div_node.className = 'card-body'; let files_body_ul_node = document.createElement('UL'); - files_body_ul_node.className = 'list-group list-group-flush'; + files_body_ul_node.id = 'event_session_files_list_'+value.id; + files_body_ul_node.className = 'list-group list-group-flush session_files_list event_files_list'; files_body_div_node.appendChild(files_body_ul_node); @@ -162,6 +165,7 @@ exports.render_event_session_records = async function () { // Presentations let presentations_div_node = document.createElement('DIV'); + presentations_div_node.id = 'session_presentations_'+value.id; presentations_div_node.className = 'card session_presentations'; let presentations_header_div_node = document.createElement('DIV'); @@ -174,7 +178,9 @@ exports.render_event_session_records = async function () { presentations_body_div_node.className = 'card-body'; let presentations_body_ul_node = document.createElement('UL'); - presentations_body_ul_node.className = 'list-group list-group-flush'; + presentations_body_ul_node.id = 'session_presentations_list_'+value.id; + presentations_body_ul_node.className = 'list-group list-group-flush session_presentations_list'; + presentations_body_ul_node.setAttribute('data-session_id', value.id); presentations_body_div_node.appendChild(presentations_body_ul_node); @@ -191,7 +197,7 @@ exports.render_event_session_records = async function () { console.log('Event session not it.'); } }).then(function() { - console.log('idb_to_ui: Iterate tbl_event_session complete') + console.log('idb_to_ui: Iterate tbl_event_session complete'); tbl_event_session_complete = true; }).then(function() { // Second: remove sessions from the launcher sessions menu and sessions list @@ -200,34 +206,36 @@ exports.render_event_session_records = async function () { console.log('Looking for removed sessions...'); let session_list_items = document.getElementById('sessions_menu').getElementsByTagName('ul')[0].childNodes; - console.log(session_list_items); - //console.log(session_list_items.length); + //console.log(session_list_items); - for (var i in session_list_items) { - console.log(session_list_items[i].getAttribute('data-session_id')); - //console.log(session_list_items[i]); - let session_id = session_list_items[i].getAttribute('data-session_id') - let session_valid = false; - - tbl_event_session.iterate(function(value, key, iteration) { - //console.log(value.event_id+' ?= '+event_id+' : '+value.event_location_id+' ?= '+event_location_id+' : '+value.id+' ?= '+session_id); - if (value.event_id == event_id && value.event_location_id == event_location_id && value.id == session_id) { - // The session is still part of the event and the location - session_valid = true; - } else { - // The session is no longer part of the event and or the location - //console.log('Need to remove session id '+session_id); - } - }).then(function() { - console.log('idb_to_ui: Iterate tbl_event_session looking for sessions to remove is complete') - if (session_valid) { - console.log('Keep session id '+session_id); - } else { - console.log('Remove session id '+session_id); - document.getElementById('menu_event_session_'+session_id).remove(); // Remove the node from the launcher sessions menu list - document.getElementById('detail_session_'+session_id).remove(); // Remove the node from the launcher sessions list - } - }); + let session_list = document.getElementById('sessions_menu').getElementsByTagName('ul')[0].children; + + if (session_list_items.length) { + for (let i=0, len=session_list_items.length; i < len; i++) { + console.log('session_id='+session_list_items[i].getAttribute('data-session_id')); + let session_id = session_list_items[i].getAttribute('data-session_id'); + let session_valid = false; + + tbl_event_session.iterate(function(value, key, iteration) { + //console.log(value.event_id+' ?= '+event_id+' : '+value.event_location_id+' ?= '+event_location_id+' : '+value.id+' ?= '+session_id); + if (value.event_id == event_id && value.event_location_id == event_location_id && value.id == session_id) { + // The session is still part of the event and the location + session_valid = true; + } else { + // The session is no longer part of the event and or the location + //console.log('Need to remove session id '+session_id); + } + }).then(function() { + console.log('idb_to_ui: Iterate tbl_event_session looking for sessions to remove is complete') + if (session_valid) { + //console.log('Keep session id '+session_id); + } else { + console.log('Remove session id '+session_id); + document.getElementById('menu_event_session_'+session_id).remove(); // Remove the node from the launcher sessions menu list + document.getElementById('detail_session_'+session_id).remove(); // Remove the node from the launcher sessions list + } + }); + } } }); @@ -251,144 +259,167 @@ exports.render_event_presentation_records = async function (events) { let launcher_sessions = document.getElementById('launcher_sessions').childNodes; //_list_items console.log(launcher_sessions); - console.log(tbl_event_presentation); - /* - loop through the sessions list (not table) { - let session_id = ; - attempt to loop through list of presentations (possibly empty) { - let presentation_id = ; - let presentation_id_found = false; - iterate through tbl_event_presentation - if (li presentation_id = tbl_event_presentation.id and session id = tbl_event_presentation.event_session_id) { - update the presentation_id - presentation_id_found = true; - } else if (session id = tbl_event_presentation.event_session_id) { - add in the new presentation_id from the table - presentation_id_found = true; - } - if (presentation_id_found == false) { - // remove the presentation - } - } - } - */ - - - - for (let i in launcher_sessions) { - console.log(launcher_sessions[i].getAttribute('data-session_id')); + for (let i=0, len=launcher_sessions.length; i < len; i++) { + //for (let i in launcher_sessions) { + console.log('Current launcher session_id='+launcher_sessions[i].getAttribute('data-session_id')); let session_id = launcher_sessions[i].getAttribute('data-session_id'); - //console.log(launcher_sessions[i].getElementsByClassName('session_presentations')[0].getElementsByTagName('ul').childElementCount); - let presentations_list = launcher_sessions[i].getElementsByClassName('session_presentations')[0].getElementsByTagName('ul')[0].childNodes; console.log(presentations_list); - //console.log(presentations_list.length); + + // First: update or delete presentations if (presentations_list.length) { console.log('Presentations listed under this session (id='+session_id+'). (launcher sessions loop i = '+i+')'); console.log(launcher_sessions[i].getElementsByClassName('session_presentations')[0].getElementsByTagName('ul')); - /* - * loop through list of presentations - * if in - */ - await tbl_event_presentation.iterate(function(value, key, iteration) { - if (document.getElementById('event_presentation_'+value.id)) { - // Update the launcher presentations list for a session - document.getElementById('event_presentation_'+value.id).getElementsByTagName('div')[0].getElementsByTagName('strong')[0].innerHTML = value.name; - let presentation_startdatetime = new Date(value.start_datetime); - document.getElementById('event_presentation_'+value.id).getElementsByTagName('div')[0].getElementsByTagName('span')[0].innerHTML = dateFns.format(presentation_startdatetime, 'h:mm A'); - } else { - - } - }).then(function() { + + for (let j=0, len=presentations_list.length; j < len; j++) { + console.log('Current launcher presentation_id='+presentations_list[j].getAttribute('data-presentation_id')); + let presentation_id = presentations_list[j].getAttribute('data-presentation_id'); - }); - - } else { - console.log('No presentations listed under this session (id='+session_id+'). Time to iterate through presentations table. (launcher sessions loop i = '+i+')'); - - let new_i = i; - console.log(new_i); - - - //if (!looping_tbl_event_presentation) { - // looping_tbl_event_presentation = true; - await tbl_event_presentation.iterate(function(value, key, iteration) { - console.log('Launcher sessions loop i: '+i+' : '+new_i); - if (value.event_session_id == session_id) { - console.log('*** Presentation id ('+value.id+') is part of this session ('+session_id+'). (launcher sessions loop i='+i+')'); - - // Add the new session to the launcher sessions list - let presentation_li_node = document.createElement('LI'); - presentation_li_node.id = 'event_presentation_'+value.id; - presentation_li_node.className = 'list-group-item'; - presentation_li_node.setAttribute('data-presentation_id', value.id); - - let presentation_li_heading_div_node = document.createElement('DIV'); - presentation_li_heading_div_node.className = 'list-group-item-heading d-flex justify-content-between align-items-center'; - - let presentation_name_strong_node = document.createElement('STRONG'); - - let presentation_name_text_node= document.createTextNode(value.name); - presentation_name_strong_node.appendChild(presentation_name_text_node); - - let presentation_heading_span_node = document.createElement('SPAN'); - presentation_heading_span_node.className = 'badge badge-pill badge-info'; - + await tbl_event_presentation.iterate(function(value, key, iteration) { + console.log('*** 1: session_id='+session_id+' | presentation.event_session_id='+value.event_session_id+' | presentation_id='+presentation_id+' | presentation.id='+value.id+' (launcher sessions loop i='+i+')'); + looping_tbl_event_presentation = true; + if (session_id == value.event_session_id && presentation_id == value.id) { + // Found presentation in that session. Updating... + console.log('Presentation was found in the session. Updating...'); + document.getElementById('event_presentation_'+value.id).getElementsByTagName('div')[0].getElementsByTagName('strong')[0].innerHTML = value.name; let presentation_startdatetime = new Date(value.start_datetime); - let presentation_heading_span_text_node = document.createTextNode(dateFns.format(presentation_startdatetime, 'h:mm A')); - presentation_heading_span_node.appendChild(presentation_heading_span_text_node); + document.getElementById('event_presentation_'+value.id).getElementsByTagName('div')[0].getElementsByTagName('span')[0].innerHTML = dateFns.format(presentation_startdatetime, 'h:mm A'); + + } else if (session_id != value.event_session_id && presentation_id == value.id) { + // Found presentation in a session that it should not be in. Removing... + console.log('Presentation exists but should not be part of this session. Removing...'); + console.log('*** Presentation id ('+value.id+') is NOT part of this session ('+session_id+'). (launcher sessions loop i='+i+')'); + document.getElementById('event_presentation_'+presentation_id).remove(); // Remove the node from the launcher presentations list + + } else { + //console.log('Not doing anything'); + } - presentation_li_heading_div_node.appendChild(presentation_name_strong_node); - presentation_li_heading_div_node.appendChild(presentation_heading_span_node); - - presentation_li_node.appendChild(presentation_li_heading_div_node); - - console.log('************ ISSUE ************'); - console.log(launcher_sessions[i].getElementsByClassName('session_presentations')); - //launcher_sessions[i].getElementsByClassName('session_presentations')[0].getElementsByTagName('ul')[0].appendChild(presentation_li_node); - let launcher_session_details = document.getElementById('detail_session_'+session_id); - console.log(launcher_session_details.getElementsByClassName('session_presentations')); - let session = document.getElementById('detail_session_'+session_id).getElementsByClassName('session_presentations')[0].getElementsByTagName('ul')[0].appendChild(presentation_li_node); - } else { - console.log('*** Presentation id ('+value.id+') is NOT part of this session ('+session_id+'). (launcher sessions loop i='+i+')'); - } - }).then(function() { - console.log('idb_to_ui: Iterate tbl_event_presentation looking for presentations to update or add is complete'); - looping_tbl_event_presentation = true; - //tbl_event_presentation_iterate_count++; - /* - if (session_valid) { - console.log('Keep session id '+session_id); - } else { - console.log('Remove session id '+session_id); - document.getElementById('menu_event_session_'+session_id).remove(); // Remove the node from the launcher sessions menu list - document.getElementById('detail_session_'+session_id).remove(); // Remove the node from the launcher sessions list - } - */ - }); - - //} else { - // console.log('Waiting until tbl_event_presentation has finished iterating...'); - //} + }).then(function() { + console.log('idb_to_ui: Iterate tbl_event_presentation looking for presentations to update or remove is complete'); + looping_tbl_event_presentation = false; + }); + } - /* -
-
Presentations:
-
-
    -
    -
    - */ + } else { // Close for if presentations_list.length - - } + } // Close for if presentations_list.length + + + // Now that the updates and removals have been done we need to add presentations. + await tbl_event_presentation.iterate(function(value, key, iteration) { + console.log('*** 2: session_id='+session_id+' | presentation.event_session_id='+value.event_session_id+' | presentation.id='+value.id+' (launcher sessions loop i='+i+')'); + looping_tbl_event_presentation = true; + + let add_presentation = true; + + if (session_id == value.event_session_id) { + // This presentation should be part of the session. Adding if not there... + + presentations_list = launcher_sessions[i].getElementsByClassName('session_presentations')[0].getElementsByTagName('ul')[0].childNodes; + console.log(presentations_list); + + if (presentations_list.length) { + // One more presentations are already in this session. + // Need to check if this one needs to be added. + for (let j=0, len=presentations_list.length; j < len; j++) { + let presentation_id = presentations_list[j].getAttribute('data-presentation_id'); + if (presentation_id == value.id) { + // Nothing here so it for sure needs to be added. + add_presentation = false; + } else { + // Don't reset the add_presentation back to true + } + } + } else { + // Nothing here, so it for sure needs to be added. + //add_presentation = true; + } + } else { + add_presentation = false; + } + + + if (add_presentation) { + // Presentation not found. Adding... + console.log('Presentation was not found in the session but should be. Adding...'); + console.log('Presentation id ('+value.id+') is part of this session ('+session_id+'). (launcher sessions loop i='+i+')'); + + // Add the new presentation to the launcher presentation list + let presentation_li_node = document.createElement('LI'); + presentation_li_node.id = 'event_presentation_'+value.id; + presentation_li_node.className = 'list-group-item event_presentation'; + presentation_li_node.setAttribute('data-presentation_id', value.id); + + let presentation_li_heading_div_node = document.createElement('DIV'); + presentation_li_heading_div_node.className = 'list-group-item-heading d-flex justify-content-between align-items-center'; + + let presentation_name_strong_node = document.createElement('STRONG'); + + let presentation_name_text_node= document.createTextNode(value.name); + presentation_name_strong_node.appendChild(presentation_name_text_node); + + let presentation_heading_span_node = document.createElement('SPAN'); + presentation_heading_span_node.className = 'badge badge-pill badge-info'; + + let presentation_startdatetime = new Date(value.start_datetime); + let presentation_heading_span_text_node = document.createTextNode(dateFns.format(presentation_startdatetime, 'h:mm A')); + presentation_heading_span_node.appendChild(presentation_heading_span_text_node); + + presentation_li_heading_div_node.appendChild(presentation_name_strong_node); + presentation_li_heading_div_node.appendChild(presentation_heading_span_node); + + + let presentation_li_text_div_node = documerender_event_file_recordsnt.createElement('DIV'); + //presentation_li_text_div_node.id = 'event_presentation_files_'+value.id; + presentation_li_text_div_node.className = 'list-group-item-text'; + + let presentation_files_ul_group_node = document.createElement('UL'); + presentation_files_ul_group_node.id = 'event_presentation_files_list_'+value.id; + presentation_files_ul_group_node.className = 'list-group list-group-flush presentation_files presentation_files_list event_files_list'; + + let presentation_presenters_ul_group_node = document.createElement('UL'); + presentation_presenters_ul_group_node.id = 'event_presentation_presenters_'+value.id; + presentation_presenters_ul_group_node.className = 'list-group list-group-flush presentation_presenters presentation_presenters_list'; + presentation_presenters_ul_group_node.setAttribute('data-presentation_id', value.id); + + presentation_li_text_div_node.appendChild(presentation_files_ul_group_node); + presentation_li_text_div_node.appendChild(presentation_presenters_ul_group_node); + + + presentation_li_node.appendChild(presentation_li_heading_div_node); + presentation_li_node.appendChild(presentation_li_text_div_node); + + + //console.log(launcher_sessions[i].getElementsByClassName('session_presentations')); + let launcher_session_details = document.getElementById('detail_session_'+session_id); + //console.log(launcher_session_details.getElementsByClassName('session_presentations')); + + // Trying to remove old ID in case there is one already rendered + try { + document.getElementById('event_presentation_'+value.id).remove(); + } + catch(err) { + console.log('A node with the ID of event_presentation_'+value.id+' was not found.'); + console.log(err.message); + } + + let session = document.getElementById('detail_session_'+session_id).getElementsByClassName('session_presentations')[0].getElementsByTagName('ul')[0].appendChild(presentation_li_node); + presentation_id_found = true; + } else { + // Presentation not part of this session. Moving on... + //console.log('Presentation was not found in the session and should not be. Moving on...'); + //console.log('*** Presentation id ('+value.id+') is not part of this session ('+session_id+'). (launcher sessions loop i='+i+')'); + } + + }).then(function() { + console.log('idb_to_ui: Iterate tbl_event_presentation looking for presentations to add is complete'); + looping_tbl_event_presentation = false; + }); - //} else { - // console.log('Waiting until launcher_sessions has finished looping...'); - //} } @@ -401,8 +432,95 @@ exports.render_event_presention_file_records = function (events) { } -exports.render_event_presenter_records = function (events) { +exports.render_event_presenter_records = async function (events) { console.log('Rendering event presenter records...'); + console.log('****************** Presenters ******************'); + + let session_presentations_lists = document.getElementsByClassName('presentation_presenters'); // from the UL nodes for presenters + console.log(session_presentations_lists); + + // First: Loop through the presenters table looking for presenters for each presentation list + await tbl_event_presenter.iterate(function(value, key, iteration) { + let presenter_id = value.id; + console.log('presenter_id='+presenter_id); + for (var i = 0; i < session_presentations_lists.length; i++) { + let presentation_id = session_presentations_lists[i].getAttribute('data-presentation_id'); + console.log('presentation_id='+presentation_id); + + // Check if this presenter is part of this presentation + let add_presenter_id = true; // Set flag to true. Update if found. Add if not found. + if (presentation_id == value.event_presentation_id) { + // Get a list of list items under the UL presenters node for a presentation + let presentation_presenters_list_items = session_presentations_lists[i].children; + + if (presentation_presenters_list_items.length) { + for (let j=0, len=presentation_presenters_list_items.length; j < len; j++) { + console.log('li_presenter_id='+presentation_presenters_list_items[j].getAttribute('data-presenter_id')); + let li_presenter_id = presentation_presenters_list_items[j].getAttribute('data-presenter_id'); + + if ( presenter_id == li_presenter_id ) { + // Update the presenter information + add_presenter_id = false; + } else { + // Remove presenter here????? + // NOTE: This section is not finished!!! + } + } + + + } else { + } + + + + } else { + // Remove presenter here????? + // NOTE: This section is not finished!!! + add_presenter_id = false; + } + + + // The presenter ID was not found. Need to add. + if ( add_presenter_id ) { + console.log('Adding this presenter ('+presenter_id+') to the list of presenters for this presentation ('+presentation_id+')'); + let presenter_li_node = document.createElement('LI'); + presenter_li_node.id = 'event_presenter_'+presenter_id; + presenter_li_node.className = 'list-group-item event_presenter'; + presenter_li_node.setAttribute('data-presenter_id', presenter_id); + + let presenter_name_strong_node = document.createElement('STRONG'); + presenter_name_strong_node.className = 'list-group-item-heading presenter_name'; + + let presenter_name_text_node= document.createTextNode(value.given_name+' '+value.family_name); + presenter_name_strong_node.appendChild(presenter_name_text_node); + + presenter_li_node.appendChild(presenter_name_strong_node); + + + let presentation_presenters_ul_group_node = document.createElement('UL'); + presentation_presenters_ul_group_node.id = 'event_presentation_presenter_files_'+presenter_id; + presentation_presenters_ul_group_node.className = 'list-group list-group-flush list-group-item-text presenter_files presenter_files_list event_files_list'; + presentation_presenters_ul_group_node.setAttribute('data-presenter_id', presenter_id); + + presenter_li_node.appendChild(presentation_presenters_ul_group_node); + + + console.log(document.getElementById('event_presentation_presenters_'+presentation_id)); + document.getElementById('event_presentation_presenters_'+presentation_id).appendChild(presenter_li_node); + //document.getElementById('event_presentation_presenters_'+presentation_id).appendChild(presentation_presenters_ul_group_node); + + } else { + console.log('This presenter ('+presenter_id+') is already part of the list of presenters for this presentation ('+presentation_id+')'); + } + + + + } + }).then(function() { + console.log('idb_to_ui: Iterate tbl_event_presenter looking for presenters to??????? update or remove is complete'); + looping_tbl_event_presentation = false; + }); + } @@ -411,6 +529,8 @@ exports.render_event_presenter_file_records = function (events) { } + + /* Updated 2020-01-31 */ function index_launcher_sessions(class_name) { console.log('Indexing launcher sessions with class name: '+class_name); @@ -428,15 +548,15 @@ function index_launcher_sessions(class_name) { /* Updated 2020-01-31 */ function view_session(session_id) { var class_elements = document.getElementsByClassName('session_detail'); // This class name should be the class names for each div container - console.log('*** View session ID: '+session_id); + console.log('View session ID: '+session_id); for (var i = 0; i < class_elements.length; i++) { - console.log('*** checking: '+class_elements[i].getAttribute('data-session_id')); + //console.log('*** checking: '+class_elements[i].getAttribute('data-session_id')); if (class_elements[i].getAttribute('data-session_id') == session_id) { - console.log('show'); + //console.log('show'); class_elements[i].classList.remove('d-none'); class_elements[i].classList.add('d-block'); } else { - console.log('hide'); + //console.log('hide'); class_elements[i].classList.remove('d-block'); class_elements[i].classList.add('d-none'); } diff --git a/config.json b/config.json index 02d755d..765d6b7 100644 --- a/config.json +++ b/config.json @@ -32,9 +32,9 @@ "idb_check_period": 30000, "idb_event_check_period": 120000, "idb_event_location_check_period": 90000, - "idb_event_session_check_period": 60000, - "idb_event_presentation_check_period": 60000, - "idb_event_presenter_check_period": 60000, + "idb_event_session_check_period": 90000, + "idb_event_presentation_check_period": 90000, + "idb_event_presenter_check_period": 30000, "idb_event_file_check_period": 60000, "host_file_cache_path": "file_cache", "host_file_cache_check_period": 30000,