").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),!c.settings.submitHandler||(e=c.settings.submitHandler.call(c,c.currentForm,b),d&&d.remove(),void 0!==e&&e)}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c,d;return a(this[0]).is("form")?b=this.validate().form():(d=[],b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b,b||(d=d.concat(c.errorList))}),c.errorList=d),b},rules:function(b,c){var d,e,f,g,h,i,j=this[0];if(null!=j&&(!j.form&&j.hasAttribute("contenteditable")&&(j.form=this.closest("form")[0],j.name=this.attr("name")),null!=j.form)){if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(a,b){i[b]=f[b],delete f[b]}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g)),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}}),a.extend(a.expr.pseudos||a.expr[":"],{blank:function(b){return!a.trim(""+a(b).val())},filled:function(b){var c=a(b).val();return null!==c&&!!a.trim(""+c)},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:void 0===c?b:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",pendingClass:"pending",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(b,c){var d=[16,17,18,20,35,36,37,38,39,40,45,144,225];9===c.which&&""===this.elementValue(b)||a.inArray(c.keyCode,d)!==-1||(b.name in this.submitted||b.name in this.invalid)&&this.element(b)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}."),step:a.validator.format("Please enter a multiple of {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){!this.form&&this.hasAttribute("contenteditable")&&(this.form=a(this).closest("form")[0],this.name=a(this).attr("name"));var c=a.data(this.form,"validator"),d="on"+b.type.replace(/^validate/,""),e=c.settings;e[d]&&!a(this).is(e.ignore)&&e[d].call(c,this,b)}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){d[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).on("focusin.validate focusout.validate keyup.validate",":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], [type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox'], [contenteditable], [type='button']",b).on("click.validate","select, option, [type='radio'], [type='checkbox']",b),this.settings.invalidHandler&&a(this.currentForm).on("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c,d,e=this.clean(b),f=this.validationTargetFor(e),g=this,h=!0;return void 0===f?delete this.invalid[e.name]:(this.prepareElement(f),this.currentElements=a(f),d=this.groups[f.name],d&&a.each(this.groups,function(a,b){b===d&&a!==f.name&&(e=g.validationTargetFor(g.clean(g.findByName(a))),e&&e.name in g.invalid&&(g.currentElements.push(e),h=g.check(e)&&h))}),c=this.check(f)!==!1,h=h&&c,c?this.invalid[f.name]=!1:this.invalid[f.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),a(b).attr("aria-invalid",!c)),h},showErrors:function(b){if(b){var c=this;a.extend(this.errorMap,b),this.errorList=a.map(this.errorMap,function(a,b){return{message:a,element:c.findByName(b)[0]}}),this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.invalid={},this.submitted={},this.prepareForm(),this.hideErrors();var b=this.elements().removeData("previousValue").removeAttr("aria-invalid");this.resetElements(b)},resetElements:function(a){var b;if(this.settings.unhighlight)for(b=0;a[b];b++)this.settings.unhighlight.call(this,a[b],this.settings.errorClass,""),this.findByName(a[b].name).removeClass(this.settings.validClass);else a.removeClass(this.settings.errorClass).removeClass(this.settings.validClass)},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)void 0!==a[b]&&null!==a[b]&&a[b]!==!1&&c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea, [contenteditable]").not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function(){var d=this.name||a(this).attr("name");return!d&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.hasAttribute("contenteditable")&&(this.form=a(this).closest("form")[0],this.name=d),!(d in c||!b.objectLength(a(this).rules()))&&(c[d]=!0,!0)})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},resetInternals:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([])},reset:function(){this.resetInternals(),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d,e=a(b),f=b.type;return"radio"===f||"checkbox"===f?this.findByName(b.name).filter(":checked").val():"number"===f&&"undefined"!=typeof b.validity?b.validity.badInput?"NaN":e.val():(c=b.hasAttribute("contenteditable")?e.text():e.val(),"file"===f?"C:\\fakepath\\"===c.substr(0,12)?c.substr(12):(d=c.lastIndexOf("/"),d>=0?c.substr(d+1):(d=c.lastIndexOf("\\"),d>=0?c.substr(d+1):c)):"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f,g=a(b).rules(),h=a.map(g,function(a,b){return b}).length,i=!1,j=this.elementValue(b);if("function"==typeof g.normalizer?f=g.normalizer:"function"==typeof this.settings.normalizer&&(f=this.settings.normalizer),f){if(j=f.call(b,j),"string"!=typeof j)throw new TypeError("The normalizer should return a string value.");delete g.normalizer}for(d in g){e={method:d,parameters:g[d]};try{if(c=a.validator.methods[d].call(this,j,b,e.parameters),"dependency-mismatch"===c&&1===h){i=!0;continue}if(i=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(k){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",k),k instanceof TypeError&&(k.message+=". Exception occurred when checking element "+b.id+", check the '"+e.method+"' method."),k}}if(!i)return this.objectLength(g)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;aWarning: No message defined for "+b.name+""),e=/\$?\{(\d+)\}/g;return"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),d},formatAndAdd:function(a,b){var c=this.defaultMessage(a,b);this.errorList.push({message:c,element:a,method:b.method}),this.errorMap[a.name]=c,this.submitted[a.name]=c},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g,h=this.errorsFor(b),i=this.idOrName(b),j=a(b).attr("aria-describedby");h.length?(h.removeClass(this.settings.validClass).addClass(this.settings.errorClass),h.html(c)):(h=a("<"+this.settings.errorElement+">").attr("id",i+"-error").addClass(this.settings.errorClass).html(c||""),d=h,this.settings.wrapper&&(d=h.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement.call(this,d,a(b)):d.insertAfter(b),h.is("label")?h.attr("for",i):0===h.parents("label[for='"+this.escapeCssMeta(i)+"']").length&&(f=h.attr("id"),j?j.match(new RegExp("\\b"+this.escapeCssMeta(f)+"\\b"))||(j+=" "+f):j=f,a(b).attr("aria-describedby",j),e=this.groups[b.name],e&&(g=this,a.each(g.groups,function(b,c){c===e&&a("[name='"+g.escapeCssMeta(b)+"']",g.currentForm).attr("aria-describedby",h.attr("id"))})))),!c&&this.settings.success&&(h.text(""),"string"==typeof this.settings.success?h.addClass(this.settings.success):this.settings.success(h,b)),this.toShow=this.toShow.add(h)},errorsFor:function(b){var c=this.escapeCssMeta(this.idOrName(b)),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+this.escapeCssMeta(d).replace(/\s+/g,", #")),this.errors().filter(e)},escapeCssMeta:function(a){return a.replace(/([\\!"#$%&'()*+,.\/:;<=>?@\[\]^`{|}~])/g,"\\$1")},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+this.escapeCssMeta(b)+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return!this.dependTypes[typeof a]||this.dependTypes[typeof a](a,b)},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(b){this.pending[b.name]||(this.pendingRequest++,a(b).addClass(this.settings.pendingClass),this.pending[b.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],a(b).removeClass(this.settings.pendingClass),c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.submitButton&&a("input:hidden[name='"+this.submitButton.name+"']",this.currentForm).remove(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b,c){return c="string"==typeof c&&c||"remote",a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,{method:c})})},destroy:function(){this.resetForm(),a(this.currentForm).off(".validate").removeData("validator").find(".validate-equalTo-blur").off(".validate-equalTo").removeClass("validate-equalTo-blur")}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},normalizeAttributeRule:function(a,b,c,d){/min|max|step/.test(c)&&(null===b||/number|range|text/.test(b))&&(d=Number(d),isNaN(d)&&(d=void 0)),d||0===d?a[c]=d:b===c&&"range"!==b&&(a[c]=!0)},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),this.normalizeAttributeRule(e,g,c,d);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),this.normalizeAttributeRule(e,g,c,d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0===e.param||e.param:(a.data(c.form,"validator").resetElements(a(c)),delete b[d])}}),a.each(b,function(d,e){b[d]=a.isFunction(e)&&"normalizer"!==d?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:b.length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[\/?#]\S*)?$/i.test(a)},date:function(a,b){return this.optional(b)||!/Invalid|NaN/.test(new Date(a).toString())},dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e<=d},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||a<=c},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},step:function(b,c,d){var e,f=a(c).attr("type"),g="Step attribute on input type "+f+" is not supported.",h=["text","number","range"],i=new RegExp("\\b"+f+"\\b"),j=f&&!i.test(h.join()),k=function(a){var b=(""+a).match(/(?:\.(\d+))?$/);return b&&b[1]?b[1].length:0},l=function(a){return Math.round(a*Math.pow(10,e))},m=!0;if(j)throw new Error(g);return e=k(d),(k(b)>e||l(b)%l(d)!==0)&&(m=!1),this.optional(c)||m},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-equalTo-blur").length&&e.addClass("validate-equalTo-blur").on("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d,e){if(this.optional(c))return"dependency-mismatch";e="string"==typeof e&&e||"remote";var f,g,h,i=this.previousValue(c,e);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),i.originalMessage=i.originalMessage||this.settings.messages[c.name][e],this.settings.messages[c.name][e]=i.message,d="string"==typeof d&&{url:d}||d,h=a.param(a.extend({data:b},d.data)),i.old===h?i.valid:(i.old=h,f=this,this.startRequest(c),g={},g[c.name]=b,a.ajax(a.extend(!0,{mode:"abort",port:"validate"+c.name,dataType:"json",data:g,context:f.currentForm,success:function(a){var d,g,h,j=a===!0||"true"===a;f.settings.messages[c.name][e]=i.originalMessage,j?(h=f.formSubmitted,f.resetInternals(),f.toHide=f.errorsFor(c),f.formSubmitted=h,f.successList.push(c),f.invalid[c.name]=!1,f.showErrors()):(d={},g=a||f.defaultMessage(c,{method:e,parameters:b}),d[c.name]=i.message=g,f.invalid[c.name]=!0,f.showErrors(d)),i.valid=j,f.stopRequest(c,j)}},d)),"pending")}}});var b,c={};return a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,d){var e=a.port;"abort"===a.mode&&(c[e]&&c[e].abort(),c[e]=d)}):(b=a.ajax,a.ajax=function(d){var e=("mode"in d?d:a.ajaxSettings).mode,f=("port"in d?d:a.ajaxSettings).port;return"abort"===e?(c[f]&&c[f].abort(),c[f]=b.apply(this,arguments),c[f]):b.apply(this,arguments)}),a});!function(e){var n;if("function"==typeof define&&define.amd&&(define(e),n=!0),"object"==typeof exports&&(module.exports=e(),n=!0),!n){var t=window.Cookies,o=window.Cookies=e();o.noConflict=function(){return window.Cookies=t,o}}}(function(){function e(){for(var e=0,n={};e
Phát triển phần mềm là một quá trình đòi hỏi sự kết hợp của nhiều kỹ thuật và phương pháp khác nhau để đáp ứng các yêu cầu và mục tiêu của dự án. Quy trình phát triển phần mềm là một bước quan trọng để tạo ra một sản phẩm phần mềm chất lượng cao, đáp ứng được nhu cầu của khách hàng. Vậy cụ thể quy trình phát triển phần mềm là gì, gồm bao nhiêu bước. Hãy cùng Tothost tìm hiểu trong bài viết này nhé!
Mục lục
Mục lục
1. Quy trình phát triển phần mềm là gì?
SDLC viết tắt của Software Development Life Cycle (Quy trình phát triển phần mềm) là một tập hợp các bước được thực hiện để tạo ra một sản phẩm phần mềm chất lượng cao và đáp ứng được nhu cầu của khách hàng. Quy trình này thường bao gồm các giai đoạn khác nhau như thu thập yêu cầu, thiết kế, phát triển, kiểm thử, triển khai và bảo trì.
Các giai đoạn trong quy trình phát triển phần mềm thường được thực hiện theo một trình tự nhất định và được phân công cho các nhóm và cá nhân khác nhau trong tổ chức. Ngoài ra, quy trình SDLC còn đòi hỏi sự sử dụng các công cụ và kỹ thuật khác nhau để hỗ trợ cho các bước trong quy trình.
Một quy trình phát triển phần mềm hiệu quả có thể giúp đảm bảo rằng sản phẩm phần mềm được tạo ra đáp ứng được các yêu cầu của khách hàng và đáp ứng các tiêu chuẩn chất lượng và hiệu suất. Nó cũng giúp tối ưu hóa quá trình phát triển, giảm thiểu chi phí và thời gian phát triển và đảm bảo sự thành công của dự án SDLC.
2. Các giai đoạn phát triển phần mềm
Nhìn chung, quy trình SDLC thường được chia làm 6 giai đoạn.
2.1. Analysis (Lên kế hoạch và phân tích yêu cầu)
Trước tiên, khi bắt đầu xây dựng một phần mềm hay hệ thống nào, chúng ta cũng cần phải biết nhu cầu của khách hàng là gì. Những chức năng nào là quan trọng và cần được thực hiện, những công nghệ nào phù hợp trong phần mềm mà khách hàng mong muốn. Đây sẽ là bước cực kỳ quan trọng và đặt nền móng cho một phần mềm tốt có thể triển khai đến tay khách hàng.
Trong giai đoạn này, người quản lý cùng với các kỹ sư của mình sẽ đưa ra kế hoạch sơ bộ cho quá trình xây dựng phần mềm dự kiến. Cùng với đó là thống nhất và chọn ra mô hình phát triển phần mềm nào là phù hợp cho ứng dụng cần xây dựng.
2.2. Design (Thiết kế phần mềm)
Từ những yêu cầu và phân tích đã được thu thập trong bước bên trên, trong giai đoạn này, các nhà phát triển phần mềm cần vạch ra được kiến trúc và thiết kế chi tiết của phần mềm. Đây là giai đoạn quan trọng để đảm bảo tính linh hoạt, dễ bảo trì, mở rộng và tái sử dụng của phần mềm.
Giai đoạn thiết kế thường bao gồm các công việc sau:
Thiết kế hệ thống: Xác định các yêu cầu của phần mềm, đánh giá các rủi ro, xác định kiến trúc hệ thống, các thành phần chính và cách chúng tương tác với nhau.
Thiết kế kiến trúc: Xây dựng kiến trúc tổng thể của phần mềm, bao gồm cả kiến trúc của ứng dụng, cơ sở dữ liệu, giao diện người dùng và hệ thống liên kết.
Thiết kế chi tiết: Thực hiện các công việc phân tích chi tiết hơn, bao gồm thiết kế lớp, thiết kế phương thức, thiết kế cấu trúc dữ liệu và các luồng dữ liệu giữa các thành phần.
Thiết kế giao diện người dùng: Thiết kế các giao diện người dùng cho phần mềm để đảm bảo tính tiện dụng và dễ sử dụng cho người dùng cuối.
Đánh giá thiết kế: Đánh giá thiết kế của phần mềm để đảm bảo tính khả thi, đảm bảo các yêu cầu được đáp ứng và đảm bảo rằng thiết kế sẽ tương thích với các công nghệ khác trong hệ thống.
Xác nhận thiết kế: Xác nhận thiết kế được hoàn thành và thông qua cho giai đoạn triển khai của quy trình phát triển phần mềm.
Giai đoạn thiết kế là bước rất quan trọng trong quy trình phát triển phần mềm vì nó đóng vai trò quyết định đến kiến trúc, tính năng và hiệu suất của phần mềm.
2.3. Development (Coding)
Đây có lẽ là giai đoạn quan trọng nhất trong quá trình phát triển phần mềm, bởi lẽ ở giai đoạn này, các nhà phát triển phần mềm sẽ bắt đầu lập trình (Coding), sử dụng các ngôn ngữ lập trình để triển khai cho các bản thiết kế đã được thực hiện.
Giai đoạn coding là một phần rất quan trọng trong quy trình phát triển phần mềm vì nó tạo ra các tính năng và chức năng của phần mềm. Việc lập trình chính xác và đảm bảo tính đúng đắn của mã rất quan trọng để đảm bảo chất lượng của phần mềm.
2.4. Testing (Kiểm thử)
Sau khi hoàn thành xong giai đoạn 3, có nghĩa lúc này, sản phẩm phần mềm đã được hoàn thành. Nhưng liệu chúng có đúng yêu cầu của khách hàng hay không. Hay còn tồn đọng bất kỳ lỗi nào trong mã nguồn hay không. Vấn đề kiểm tra và phát hiện lỗi sẽ thuộc về người kiểm thử (tester). Các tester sẽ tạo các test case (kịch bản kiểm thử) và tiến hành kiểm thử phần mềm. Mục đích chính của giai đoạn này là tìm ra lỗi sao cho phần mềm được đưa ra đảm bảo đúng yêu cầu của khách hàng
Sau khi tester tìm được ra bất kỳ lỗi nào thì sẽ được tổng hợp và đưa lại cho bộ phận Coding để thực hiện rà soát và xây dựng lại phần mềm. Các bước như thế cứ lặp lại cho đến khi phần mềm không còn lỗi và đạt đúng nhu cầu của khách hàng.
2.5. Deployment (triển khai)
Sau khi hoàn thành giai đoạn kiểm thử, có nghĩa lúc này phần mềm đã được hoạt động một cách trơn tru và đảm bảo đúng nhu cầu của khách hàng. Trong giai đoạn này, các chuyên gia triển khai sẽ thực hiện các hoạt động như sau:
Chuẩn bị môi trường triển khai: Chuẩn bị môi trường triển khai phần mềm, bao gồm cấu hình phần cứng và phần mềm, các tài nguyên và dịch vụ hỗ trợ.
Triển khai phần mềm: Triển khai phần mềm trên môi trường triển khai đã chuẩn bị.
Kiểm tra và xác nhận: Kiểm tra và xác nhận phần mềm đã triển khai hoạt động đúng trên môi trường triển khai.
Đào tạo và hỗ trợ: Cung cấp đào tạo và hỗ trợ cho người dùng cuối, để giúp họ sử dụng phần mềm một cách hiệu quả và giải quyết các vấn đề phát sinh.
Giai đoạn deployment là giai đoạn quan trọng trong quy trình phát triển phần mềm, giúp đảm bảo rằng phần mềm được triển khai và sử dụng một cách hiệu quả.
2.6. Maintenance (Bảo trì)
Sau khi phần mềm đã được đưa vào vận hành, khi đó khách hàng đã có thể sử dụng phần mềm. Nhưng không có nghĩa, mọi việc đối với công ty đã kết thúc. Nếu chẳng may sau một thời gian sử dụng, sản phẩm phần mềm bắt đầu xuất hiện lỗi thì sao? Đó là lý do chúng ta cần giai đoạn này.
Trong quá trình sử dụng sản phẩm của khách hàng, nhóm thành viên thuộc bộ phận bảo trì trong công ty sẽ quản lý các vấn đề mà người dùng gặp phải, từ đó cho phép phần mềm được duy trì và hoạt động tốt trong thời gian dài.
3. Mô hình phát triển phần mềm
3.1. Waterfall Model (Mô hình thác nước)
Mô hình thác nước là mô hình phát triển phần mềm được thiết kế theo kiểu tuyến tính, có các bước phát triển được thực hiện theo thứ tự chuỗi. Mỗi bước tiếp theo được thực hiện sau khi bước trước đó đã hoàn thành và được chấp nhận. Các bước phát triển phần mềm trong mô hình thác nước bao gồm: yêu cầu, thiết kế, triển khai, kiểm thử và bảo trì.
3.2. V Model (Mô hình chữ V)
Mô hình chữ V là mô hình phát triển phần mềm dựa trên mô hình thác nước, nhưng tập trung vào kiểm thử và đảm bảo chất lượng sản phẩm.
Trong mô hình này, các bước phát triển phần mềm được đặt theo hình chữ V, trong đó phần trên của V đại diện cho các bước phát triển phần mềm, còn phần dưới của V đại diện cho các bước kiểm thử và đảm bảo chất lượng.
3.3. Agile Model (Mô hình Agile)
Mô hình Agile là một phương pháp phát triển phần mềm linh hoạt và thích ứng với môi trường thay đổi nhanh. Nó tập trung vào sự tương tác giữa các thành viên trong nhóm phát triển và khách hàng để phát triển sản phẩm có chất lượng cao và đáp ứng nhu cầu của khách hàng.
Agile phân chia quá trình phát triển sản phẩm thành các chu kỳ ngắn gọi là sprint, trong đó các tính năng được thiết kế, phát triển và kiểm thử trong một khoảng thời gian ngắn.
3.4. Scrum Model (Mô hình Scrum)
Scrum là một phương pháp quản lý dự án phát triển phần mềm trong môi trường linh hoạt và thay đổi. Nó tập trung vào việc phát triển sản phẩm trong các sprint ngắn và sử dụng các cuộc họp định kỳ để đánh giá tiến độ, cải tiến sản phẩm và giải quyết các vấn đề trong quá trình phát triển.
Scrum cũng coi khách hàng là một phần của quá trình phát triển và thường yêu cầu các bên liên quan phải thường xuyên hợp tác để đạt được mục tiêu phát triển sản phẩm.
3.5. Boehm Spiral Model (Mô hình xoắn ốc)
Mô hình Boehm Spiral là một phương pháp phát triển phần mềm dựa trên mô hình thác nước. Nó tập trung vào việc giảm thiểu rủi ro trong quá trình phát triển bằng cách phân tích và đánh giá rủi ro từ đầu đến cuối quá trình phát triển.
Boehm Spiral Model chia quá trình phát triển phần mềm thành các giai đoạn có thể lặp đi lặp lại, trong đó mỗi giai đoạn bao gồm việc phân tích, thiết kế, xây dựng và kiểm thử. Mô hình này tập trung vào việc đánh giá và quản lý rủi ro để đảm bảo rằng sản phẩm được phát triển đáp ứng các yêu cầu của khách hàng và đạt được chất lượng cao.
Lời kết
Qua bài viết Tothost cùng với mọi người đã cùng tìm hiểu về quy trình phát triển của một phần mềm. Hi vọng với kiến thức hữu ích này đã giúp các bạn có những kiến thức sơ bộ về việc phát triển phần mềm, từ đó đặt nền móng trong lĩnh vực xây dựng phần mềm của mọi người. Đọc thêm bài viết liên quan tại: https://tothost.vn/kien-thuc
Việc thay đổi mật khẩu là biện pháp quan trọng để tăng cường bảo mật và tránh được những rủi ro không mong muốn. Do đó, bước đầu tiên nên làm sau khi đăng ký dịch vụ là đổi mật khẩu. Bạn hãy làm theo hướng dẫn của TotHost để thay đổi mật khẩu trên server Linux nhé!
Ứng dụng Điện toán đám mây (Cloud Computing) là sử dụng công nghệ đám mây phục vụ cho nhiều công việc khác nhau, được kết nối qua internet. Đám mây mang lại lợi thế bao gồm khả năng mở rộng, tính linh hoạt, hiệu quả chi phí, bảo mật và đổi mới cho các tổ chức ở mọi quy mô và lĩnh vực. Do đó, nó được các tổ chức áp dụng để đạt được mục tiêu và giải quyết các vấn đề của họ.Dưới đây là Top 10 ứng dụng phổ biến nhất của điện toán đám mây.
Nếu bạn đang thắc mắc liệu có nên chuyển đổi sang Điện toán đám mây (Cloud Computing) hay vẫn nên chọn on-premise thì bài viết này sẽ giúp bạn hiểu rõ hơn về những lợi ích của việc chuyển đổi này.
Khi bạn kết nối máy tính hoặc thiết bị của mình với internet, bạn cần có địa chỉ IP. Địa chỉ IP có hai loại phân bổ: động và tĩnh. Tại bài viết này, TotHost sẽ hướng dẫn bạn Cách kiểm tra địa chỉ IP bạn đang sử dụng là động hay tĩnh.
cPanel là một control panel – hệ thống quản trị web hosting phổ biến và mạnh mẽ nhất hiện nay, hoạt động dựa trên nền tảng Linux. Nó có giao diện đơn giản, linh hoạt hỗ trợ quản trị hosting và website một cách dễ dàng. Tại đây, TotHost sẽ hướng dẫn bạn cách tạo Backup và Restore trên cPanel.
Hiện nay, công nghệ trí tuệ nhân tạo đang bùng nổ mạnh mẽ tạo ra những tiềm năng to lớn trong nhiều lĩnh vực trong cuộc sống. Để làm được điều đó thì không thể thiếu AI tạo sinh (Generative AI). Vậy, Gen AI là gì? Nó có đóng góp gì trong thực tiễn? Hãy cùng tìm hiểu qua bài viết này nhé!